blob: 788651080858e9c5605047831ec948e8cceb203a [file] [log] [blame]
Klement Sekeraf62ae122016-10-11 11:47:09 +02001from abc import abstractmethod, ABCMeta
2import socket
Klement Sekeraf62ae122016-10-11 11:47:09 +02003
Jan65209ed2016-12-05 23:29:17 +01004from util import Host
5
Klement Sekeraf62ae122016-10-11 11:47:09 +02006
7class VppInterface(object):
Matej Klotton86d87c42016-11-11 11:38:55 +01008 """Generic VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +02009 __metaclass__ = ABCMeta
10
11 @property
12 def sw_if_index(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010013 """Interface index assigned by VPP."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020014 return self._sw_if_index
15
16 @property
17 def remote_mac(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010018 """MAC-address of the remote interface "connected" to this interface."""
Matej Klotton0178d522016-11-04 11:11:44 +010019 return self._remote_hosts[0].mac
Klement Sekeraf62ae122016-10-11 11:47:09 +020020
21 @property
22 def local_mac(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010023 """MAC-address of the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020024 return self._local_mac
25
26 @property
27 def local_ip4(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010028 """Local IPv4 address on VPP interface (string)."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020029 return self._local_ip4
30
31 @property
32 def local_ip4n(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010033 """Local IPv4 address - raw, suitable as API parameter."""
Matej Klotton0178d522016-11-04 11:11:44 +010034 return socket.inet_pton(socket.AF_INET, self._local_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +020035
36 @property
37 def remote_ip4(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010038 """IPv4 address of remote peer "connected" to this interface."""
Matej Klotton0178d522016-11-04 11:11:44 +010039 return self._remote_hosts[0].ip4
Klement Sekeraf62ae122016-10-11 11:47:09 +020040
41 @property
42 def remote_ip4n(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010043 """IPv4 address of remote peer - raw, suitable as API parameter."""
Matej Klotton0178d522016-11-04 11:11:44 +010044 return socket.inet_pton(socket.AF_INET, self.remote_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +020045
46 @property
47 def local_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010048 """Local IPv6 address on VPP interface (string)."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020049 return self._local_ip6
50
51 @property
52 def local_ip6n(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010053 """Local IPv6 address - raw, suitable as API parameter."""
Matej Klotton0178d522016-11-04 11:11:44 +010054 return socket.inet_pton(socket.AF_INET6, self.local_ip6)
Klement Sekeraf62ae122016-10-11 11:47:09 +020055
56 @property
57 def remote_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010058 """IPv6 address of remote peer "connected" to this interface."""
Matej Klotton0178d522016-11-04 11:11:44 +010059 return self._remote_hosts[0].ip6
Klement Sekeraf62ae122016-10-11 11:47:09 +020060
61 @property
62 def remote_ip6n(self):
63 """IPv6 address of remote peer - raw, suitable as API parameter"""
Matej Klotton0178d522016-11-04 11:11:44 +010064 return socket.inet_pton(socket.AF_INET6, self.remote_ip6)
Klement Sekeraf62ae122016-10-11 11:47:09 +020065
66 @property
67 def name(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010068 """Name of the interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020069 return self._name
70
71 @property
72 def dump(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010073 """RAW result of sw_interface_dump for this interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020074 return self._dump
75
76 @property
77 def test(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010078 """Test case creating this interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020079 return self._test
80
Matej Klotton0178d522016-11-04 11:11:44 +010081 @property
82 def remote_hosts(self):
83 """Remote hosts list"""
84 return self._remote_hosts
85
86 @remote_hosts.setter
87 def remote_hosts(self, value):
Matej Klotton86d87c42016-11-11 11:38:55 +010088 """
89 :param list value: List of remote hosts.
90 """
Matej Klotton0178d522016-11-04 11:11:44 +010091 self._remote_hosts = value
Matej Klotton86d87c42016-11-11 11:38:55 +010092 self._hosts_by_mac = {}
93 self._hosts_by_ip4 = {}
94 self._hosts_by_ip6 = {}
95 for host in self._remote_hosts:
96 self._hosts_by_mac[host.mac] = host
97 self._hosts_by_ip4[host.ip4] = host
98 self._hosts_by_ip6[host.ip6] = host
Matej Klotton0178d522016-11-04 11:11:44 +010099
100 def host_by_mac(self, mac):
Matej Klotton86d87c42016-11-11 11:38:55 +0100101 """
Matej Klottonc5bf07f2016-11-23 15:27:17 +0100102 :param mac: MAC address to find host by.
Matej Klotton86d87c42016-11-11 11:38:55 +0100103 :return: Host object assigned to interface.
104 """
Matej Klotton0178d522016-11-04 11:11:44 +0100105 return self._hosts_by_mac[mac]
106
107 def host_by_ip4(self, ip):
Matej Klotton86d87c42016-11-11 11:38:55 +0100108 """
109 :param ip: IPv4 address to find host by.
110 :return: Host object assigned to interface.
111 """
Matej Klotton0178d522016-11-04 11:11:44 +0100112 return self._hosts_by_ip4[ip]
113
114 def host_by_ip6(self, ip):
Matej Klotton86d87c42016-11-11 11:38:55 +0100115 """
116 :param ip: IPv6 address to find host by.
117 :return: Host object assigned to interface.
118 """
Matej Klotton0178d522016-11-04 11:11:44 +0100119 return self._hosts_by_ip6[ip]
120
121 def generate_remote_hosts(self, count=1):
Matej Klotton86d87c42016-11-11 11:38:55 +0100122 """Generate and add remote hosts for the interface.
123
124 :param int count: Number of generated remote hosts.
125 """
Matej Klotton0178d522016-11-04 11:11:44 +0100126 self._remote_hosts = []
127 self._hosts_by_mac = {}
128 self._hosts_by_ip4 = {}
129 self._hosts_by_ip6 = {}
Klement Sekera7bb873a2016-11-18 07:38:42 +0100130 for i in range(
131 2, count + 2): # 0: network address, 1: local vpp address
Matej Klotton0178d522016-11-04 11:11:44 +0100132 mac = "02:%02x:00:00:ff:%02x" % (self.sw_if_index, i)
133 ip4 = "172.16.%u.%u" % (self.sw_if_index, i)
134 ip6 = "fd01:%04x::%04x" % (self.sw_if_index, i)
135 host = Host(mac, ip4, ip6)
136 self._remote_hosts.append(host)
137 self._hosts_by_mac[mac] = host
138 self._hosts_by_ip4[ip4] = host
139 self._hosts_by_ip6[ip6] = host
140
Matej Klottonc5bf07f2016-11-23 15:27:17 +0100141 @abstractmethod
142 def __init__(self, test):
143 self._test = test
144
145 self._remote_hosts = []
146 self._hosts_by_mac = {}
147 self._hosts_by_ip4 = {}
148 self._hosts_by_ip6 = {}
Matej Klotton0178d522016-11-04 11:11:44 +0100149
150 self.generate_remote_hosts()
Klement Sekeraf62ae122016-10-11 11:47:09 +0200151
152 self._local_ip4 = "172.16.%u.1" % self.sw_if_index
153 self._local_ip4n = socket.inet_pton(socket.AF_INET, self.local_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200154
Matej Klotton0178d522016-11-04 11:11:44 +0100155 self._local_ip6 = "fd01:%04x::1" % self.sw_if_index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200156 self._local_ip6n = socket.inet_pton(socket.AF_INET6, self.local_ip6)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200157
158 r = self.test.vapi.sw_interface_dump()
159 for intf in r:
160 if intf.sw_if_index == self.sw_if_index:
161 self._name = intf.interface_name.split(b'\0', 1)[0]
Klement Sekera7bb873a2016-11-18 07:38:42 +0100162 self._local_mac =\
163 ':'.join(intf.l2_address.encode('hex')[i:i + 2]
164 for i in range(0, 12, 2))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200165 self._dump = intf
166 break
167 else:
168 raise Exception(
169 "Could not find interface with sw_if_index %d "
170 "in interface dump %s" %
171 (self.sw_if_index, repr(r)))
172
Klement Sekeraf62ae122016-10-11 11:47:09 +0200173 def config_ip4(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100174 """Configure IPv4 address on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200175 addr = self.local_ip4n
176 addr_len = 24
177 self.test.vapi.sw_interface_add_del_address(
178 self.sw_if_index, addr, addr_len)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000179 self.has_ip4_config = True
180
181 def unconfig_ip4(self):
182 """Remove IPv4 address on the VPP interface"""
183 try:
184 if (self.has_ip4_config):
185 self.test.vapi.sw_interface_add_del_address(
186 self.sw_if_index,
187 self.local_ip4n,
188 24, is_add=0)
189 except AttributeError:
190 self.has_ip4_config = False
191 self.has_ip4_config = False
Klement Sekeraf62ae122016-10-11 11:47:09 +0200192
Matej Klotton86d87c42016-11-11 11:38:55 +0100193 def configure_ipv4_neighbors(self):
194 """For every remote host assign neighbor's MAC to IPv4 addresses."""
Matej Klotton0178d522016-11-04 11:11:44 +0100195 for host in self._remote_hosts:
196 macn = host.mac.replace(":", "").decode('hex')
197 ipn = host.ip4n
198 self.test.vapi.ip_neighbor_add_del(self.sw_if_index, macn, ipn)
199
Klement Sekeraf62ae122016-10-11 11:47:09 +0200200 def config_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100201 """Configure IPv6 address on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200202 addr = self._local_ip6n
203 addr_len = 64
204 self.test.vapi.sw_interface_add_del_address(
205 self.sw_if_index, addr, addr_len, is_ipv6=1)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000206 self.has_ip6_config = True
207
208 def unconfig_ip6(self):
209 """Remove IPv6 address on the VPP interface"""
210 try:
211 if (self.has_ip6_config):
212 self.test.vapi.sw_interface_add_del_address(
213 self.sw_if_index,
214 self.local_ip6n,
215 64, is_ipv6=1, is_add=0)
216 except AttributeError:
217 self.has_ip6_config = False
218 self.has_ip6_config = False
219
220 def unconfig(self):
221 """Unconfigure IPv6 and IPv4 address on the VPP interface"""
222 self.unconfig_ip4()
223 self.unconfig_ip6()
Klement Sekeraf62ae122016-10-11 11:47:09 +0200224
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000225 def set_table_ip4(self, table_id):
226 """Set the interface in a IPv4 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100227
228 .. note:: Must be called before configuring IP4 addresses."""
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000229 self.test.vapi.sw_interface_set_table(
230 self.sw_if_index, 0, table_id)
231
232 def set_table_ip6(self, table_id):
233 """Set the interface in a IPv6 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100234
235 .. note:: Must be called before configuring IP6 addresses.
236 """
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000237 self.test.vapi.sw_interface_set_table(
238 self.sw_if_index, 1, table_id)
239
Klement Sekeraf62ae122016-10-11 11:47:09 +0200240 def disable_ipv6_ra(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100241 """Configure IPv6 RA suppress on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200242 self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
243
Klement Sekeraf62ae122016-10-11 11:47:09 +0200244 def admin_up(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100245 """Put interface ADMIN-UP."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200246 self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=1)
247
248 def add_sub_if(self, sub_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100249 """Register a sub-interface with this interface.
Klement Sekeraf62ae122016-10-11 11:47:09 +0200250
251 :param sub_if: sub-interface
Klement Sekeraf62ae122016-10-11 11:47:09 +0200252 """
253 if not hasattr(self, 'sub_if'):
254 self.sub_if = sub_if
255 else:
256 if isinstance(self.sub_if, list):
257 self.sub_if.append(sub_if)
258 else:
259 self.sub_if = sub_if
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000260
261 def enable_mpls(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100262 """Enable MPLS on the VPP interface."""
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000263 self.test.vapi.sw_interface_enable_disable_mpls(
264 self.sw_if_index)