1 from abc import abstractmethod, ABCMeta
4 from util import Host, mk_ll_addr
5 from vpp_neighbor import VppNeighbor
8 class VppInterface(object):
9 """Generic VPP interface."""
10 __metaclass__ = ABCMeta
13 def sw_if_index(self):
14 """Interface index assigned by VPP."""
15 return self._sw_if_index
19 """MAC-address of the remote interface "connected" to this interface"""
20 return self._remote_hosts[0].mac
24 """MAC-address of the VPP interface."""
25 return self._local_mac
29 """Local IPv4 address on VPP interface (string)."""
30 return self._local_ip4
34 """Local IPv4 address - raw, suitable as API parameter."""
35 return socket.inet_pton(socket.AF_INET, self._local_ip4)
39 """IPv4 address of remote peer "connected" to this interface."""
40 return self._remote_hosts[0].ip4
43 def remote_ip4n(self):
44 """IPv4 address of remote peer - raw, suitable as API parameter."""
45 return socket.inet_pton(socket.AF_INET, self.remote_ip4)
49 """Local IPv6 address on VPP interface (string)."""
50 return self._local_ip6
54 """Local IPv6 address - raw, suitable as API parameter."""
55 return socket.inet_pton(socket.AF_INET6, self.local_ip6)
59 """IPv6 address of remote peer "connected" to this interface."""
60 return self._remote_hosts[0].ip6
63 def remote_ip6n(self):
64 """IPv6 address of remote peer - raw, suitable as API parameter"""
65 return socket.inet_pton(socket.AF_INET6, self.remote_ip6)
68 def local_ip6_ll(self):
69 """Local IPv6 linnk-local address on VPP interface (string)."""
70 return self._local_ip6_ll
73 def local_ip6n_ll(self):
74 """Local IPv6 link-local address - raw, suitable as API parameter."""
75 return self._local_ip6n_ll
78 def remote_ip6_ll(self):
79 """Link-local IPv6 address of remote peer
80 "connected" to this interface."""
81 return self._remote_ip6_ll
84 def remote_ip6n_ll(self):
85 """Link-local IPv6 address of remote peer
86 - raw, suitable as API parameter"""
87 return self._remote_ip6n_ll
91 """Name of the interface."""
96 """RAW result of sw_interface_dump for this interface."""
101 """Test case creating this interface."""
105 def remote_hosts(self):
106 """Remote hosts list"""
107 return self._remote_hosts
110 def remote_hosts(self, value):
112 :param list value: List of remote hosts.
114 self._remote_hosts = value
115 self._hosts_by_mac = {}
116 self._hosts_by_ip4 = {}
117 self._hosts_by_ip6 = {}
118 for host in self._remote_hosts:
119 self._hosts_by_mac[host.mac] = host
120 self._hosts_by_ip4[host.ip4] = host
121 self._hosts_by_ip6[host.ip6] = host
123 def host_by_mac(self, mac):
125 :param mac: MAC address to find host by.
126 :return: Host object assigned to interface.
128 return self._hosts_by_mac[mac]
130 def host_by_ip4(self, ip):
132 :param ip: IPv4 address to find host by.
133 :return: Host object assigned to interface.
135 return self._hosts_by_ip4[ip]
137 def host_by_ip6(self, ip):
139 :param ip: IPv6 address to find host by.
140 :return: Host object assigned to interface.
142 return self._hosts_by_ip6[ip]
144 def generate_remote_hosts(self, count=1):
145 """Generate and add remote hosts for the interface.
147 :param int count: Number of generated remote hosts.
149 self._remote_hosts = []
150 self._hosts_by_mac = {}
151 self._hosts_by_ip4 = {}
152 self._hosts_by_ip6 = {}
154 2, count + 2): # 0: network address, 1: local vpp address
155 mac = "02:%02x:00:00:ff:%02x" % (self.sw_if_index, i)
156 ip4 = "172.16.%u.%u" % (self.sw_if_index, i)
157 ip6 = "fd01:%x::%x" % (self.sw_if_index, i)
158 ip6_ll = mk_ll_addr(mac)
159 host = Host(mac, ip4, ip6, ip6_ll)
160 self._remote_hosts.append(host)
161 self._hosts_by_mac[mac] = host
162 self._hosts_by_ip4[ip4] = host
163 self._hosts_by_ip6[ip6] = host
166 def __init__(self, test):
169 self._remote_hosts = []
170 self._hosts_by_mac = {}
171 self._hosts_by_ip4 = {}
172 self._hosts_by_ip6 = {}
174 self.generate_remote_hosts()
176 self._local_ip4 = "172.16.%u.1" % self.sw_if_index
177 self._local_ip4n = socket.inet_pton(socket.AF_INET, self.local_ip4)
178 self._local_ip4_subnet = "172.16.%u.0" % self.sw_if_index
179 self._local_ip4n_subnet = socket.inet_pton(socket.AF_INET,
180 self._local_ip4_subnet)
181 self._local_ip4_bcast = "172.16.%u.255" % self.sw_if_index
182 self._local_ip4n_bcast = socket.inet_pton(socket.AF_INET,
183 self._local_ip4_bcast)
184 self.local_ip4_prefix_len = 24
185 self.has_ip4_config = False
186 self.ip4_table_id = 0
188 self._local_ip6 = "fd01:%x::1" % self.sw_if_index
189 self._local_ip6n = socket.inet_pton(socket.AF_INET6, self.local_ip6)
190 self.local_ip6_prefix_len = 64
191 self.has_ip6_config = False
192 self.ip6_table_id = 0
194 r = self.test.vapi.sw_interface_dump()
196 if intf.sw_if_index == self.sw_if_index:
197 self._name = intf.interface_name.split(b'\0', 1)[0]
199 ':'.join(intf.l2_address.encode('hex')[i:i + 2]
200 for i in range(0, 12, 2))
205 "Could not find interface with sw_if_index %d "
206 "in interface dump %s" %
207 (self.sw_if_index, repr(r)))
208 self._local_ip6_ll = mk_ll_addr(self.local_mac)
209 self._local_ip6n_ll = socket.inet_pton(socket.AF_INET6,
211 self._remote_ip6_ll = mk_ll_addr(self.remote_mac)
212 self._remote_ip6n_ll = socket.inet_pton(socket.AF_INET6,
215 def config_ip4(self):
216 """Configure IPv4 address on the VPP interface."""
217 self.test.vapi.sw_interface_add_del_address(
218 self.sw_if_index, self.local_ip4n, self.local_ip4_prefix_len)
219 self.has_ip4_config = True
221 def unconfig_ip4(self):
222 """Remove IPv4 address on the VPP interface."""
224 if self.has_ip4_config:
225 self.test.vapi.sw_interface_add_del_address(
228 self.local_ip4_prefix_len,
230 except AttributeError:
231 self.has_ip4_config = False
232 self.has_ip4_config = False
234 def configure_ipv4_neighbors(self):
235 """For every remote host assign neighbor's MAC to IPv4 addresses.
237 :param vrf_id: The FIB table / VRF ID. (Default value = 0)
239 for host in self._remote_hosts:
240 macn = host.mac.replace(":", "").decode('hex')
242 self.test.vapi.ip_neighbor_add_del(
243 self.sw_if_index, macn, ipn)
245 def config_ip6(self):
246 """Configure IPv6 address on the VPP interface."""
247 self.test.vapi.sw_interface_add_del_address(
248 self.sw_if_index, self._local_ip6n, self.local_ip6_prefix_len,
250 self.has_ip6_config = True
252 def unconfig_ip6(self):
253 """Remove IPv6 address on the VPP interface."""
255 if self.has_ip6_config:
256 self.test.vapi.sw_interface_add_del_address(
259 self.local_ip6_prefix_len,
261 except AttributeError:
262 self.has_ip6_config = False
263 self.has_ip6_config = False
265 def configure_ipv6_neighbors(self):
266 """For every remote host assign neighbor's MAC to IPv6 addresses.
268 :param vrf_id: The FIB table / VRF ID. (Default value = 0)
270 for host in self._remote_hosts:
271 macn = host.mac.replace(":", "").decode('hex')
273 self.test.vapi.ip_neighbor_add_del(
274 self.sw_if_index, macn, ipn, is_ipv6=1)
277 """Unconfigure IPv6 and IPv4 address on the VPP interface."""
281 def set_table_ip4(self, table_id):
282 """Set the interface in a IPv4 Table.
284 .. note:: Must be called before configuring IP4 addresses.
286 self.ip4_table_id = table_id
287 self.test.vapi.sw_interface_set_table(
288 self.sw_if_index, 0, self.ip4_table_id)
290 def set_table_ip6(self, table_id):
291 """Set the interface in a IPv6 Table.
293 .. note:: Must be called before configuring IP6 addresses.
295 self.ip6_table_id = table_id
296 self.test.vapi.sw_interface_set_table(
297 self.sw_if_index, 1, self.ip6_table_id)
299 def disable_ipv6_ra(self):
300 """Configure IPv6 RA suppress on the VPP interface."""
301 self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
303 def ip6_ra_config(self, no=0, suppress=0, send_unicast=0):
304 """Configure IPv6 RA suppress on the VPP interface."""
305 self.test.vapi.ip6_sw_interface_ra_config(self.sw_if_index,
310 def ip6_ra_prefix(self, address, address_length, is_no=0,
311 off_link=0, no_autoconfig=0, use_default=0):
312 """Configure IPv6 RA suppress on the VPP interface."""
313 self.test.vapi.ip6_sw_interface_ra_prefix(self.sw_if_index,
318 no_autoconfig=no_autoconfig,
319 use_default=use_default)
322 """Put interface ADMIN-UP."""
323 self.test.vapi.sw_interface_set_flags(self.sw_if_index,
326 def admin_down(self):
327 """Put interface ADMIN-down."""
328 self.test.vapi.sw_interface_set_flags(self.sw_if_index,
331 def ip6_enable(self):
332 """IPv6 Enable interface"""
333 self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index,
336 def ip6_disable(self):
337 """Put interface ADMIN-DOWN."""
338 self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index,
341 def add_sub_if(self, sub_if):
342 """Register a sub-interface with this interface.
344 :param sub_if: sub-interface
346 if not hasattr(self, 'sub_if'):
349 if isinstance(self.sub_if, list):
350 self.sub_if.append(sub_if)
354 def enable_mpls(self):
355 """Enable MPLS on the VPP interface."""
356 self.test.vapi.sw_interface_enable_disable_mpls(
359 def disable_mpls(self):
360 """Enable MPLS on the VPP interface."""
361 self.test.vapi.sw_interface_enable_disable_mpls(
364 def is_ip4_entry_in_fib_dump(self, dump):
366 if i.address == self.local_ip4n and \
367 i.address_length == self.local_ip4_prefix_len and \
368 i.table_id == self.ip4_table_id:
372 def set_unnumbered(self, ip_sw_if_index):
373 """ Set the interface to unnumbered via ip_sw_if_index """
374 self.test.vapi.sw_interface_set_unnumbered(
378 def unset_unnumbered(self, ip_sw_if_index):
379 """ Unset the interface to unnumbered via ip_sw_if_index """
380 self.test.vapi.sw_interface_set_unnumbered(
385 def set_proxy_arp(self, enable=1):
386 """ Set the interface to enable/disable Proxy ARP """
387 self.test.vapi.proxy_arp_intfc_enable_disable(
391 def query_vpp_config(self):
392 dump = self.test.vapi.sw_interface_dump()
393 return self.is_interface_config_in_dump(dump)
395 def is_interface_config_in_dump(self, dump):
397 if i.interface_name.rstrip(' \t\r\n\0') == self.name and \
398 i.sw_if_index == self.sw_if_index: