blob: 9d9712eb7ed30d5ea71ea73ca1f551080013f45c [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)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100154 self.local_ip4_prefix_len = 24
155 self.has_ip4_config = False
156 self.ip4_table_id = 0
Klement Sekeraf62ae122016-10-11 11:47:09 +0200157
Matej Klotton0178d522016-11-04 11:11:44 +0100158 self._local_ip6 = "fd01:%04x::1" % self.sw_if_index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200159 self._local_ip6n = socket.inet_pton(socket.AF_INET6, self.local_ip6)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100160 self.local_ip6_prefix_len = 64
161 self.has_ip6_config = False
162 self.ip6_table_id = 0
Klement Sekeraf62ae122016-10-11 11:47:09 +0200163
164 r = self.test.vapi.sw_interface_dump()
165 for intf in r:
166 if intf.sw_if_index == self.sw_if_index:
167 self._name = intf.interface_name.split(b'\0', 1)[0]
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100168 self._local_mac = \
Klement Sekera7bb873a2016-11-18 07:38:42 +0100169 ':'.join(intf.l2_address.encode('hex')[i:i + 2]
170 for i in range(0, 12, 2))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200171 self._dump = intf
172 break
173 else:
174 raise Exception(
175 "Could not find interface with sw_if_index %d "
176 "in interface dump %s" %
177 (self.sw_if_index, repr(r)))
178
Klement Sekeraf62ae122016-10-11 11:47:09 +0200179 def config_ip4(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100180 """Configure IPv4 address on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200181 self.test.vapi.sw_interface_add_del_address(
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100182 self.sw_if_index, self.local_ip4n, self.local_ip4_prefix_len)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000183 self.has_ip4_config = True
184
185 def unconfig_ip4(self):
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100186 """Remove IPv4 address on the VPP interface."""
Neale Ranns177bbdc2016-11-15 09:46:51 +0000187 try:
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100188 if self.has_ip4_config:
Neale Ranns177bbdc2016-11-15 09:46:51 +0000189 self.test.vapi.sw_interface_add_del_address(
190 self.sw_if_index,
191 self.local_ip4n,
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100192 self.local_ip4_prefix_len,
193 is_add=0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000194 except AttributeError:
195 self.has_ip4_config = False
196 self.has_ip4_config = False
Klement Sekeraf62ae122016-10-11 11:47:09 +0200197
Jane546d3b2016-12-08 13:10:03 +0100198 def configure_ipv4_neighbors(self, vrf_id=0):
199 """For every remote host assign neighbor's MAC to IPv4 addresses.
200
201 :param vrf_id: The FIB table / VRF ID. (Default value = 0)
202 """
Matej Klotton0178d522016-11-04 11:11:44 +0100203 for host in self._remote_hosts:
204 macn = host.mac.replace(":", "").decode('hex')
205 ipn = host.ip4n
Jane546d3b2016-12-08 13:10:03 +0100206 self.test.vapi.ip_neighbor_add_del(
207 self.sw_if_index, macn, ipn, vrf_id)
Matej Klotton0178d522016-11-04 11:11:44 +0100208
Klement Sekeraf62ae122016-10-11 11:47:09 +0200209 def config_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100210 """Configure IPv6 address on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200211 self.test.vapi.sw_interface_add_del_address(
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100212 self.sw_if_index, self._local_ip6n, self.local_ip6_prefix_len,
213 is_ipv6=1)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000214 self.has_ip6_config = True
215
216 def unconfig_ip6(self):
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100217 """Remove IPv6 address on the VPP interface."""
Neale Ranns177bbdc2016-11-15 09:46:51 +0000218 try:
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100219 if self.has_ip6_config:
Neale Ranns177bbdc2016-11-15 09:46:51 +0000220 self.test.vapi.sw_interface_add_del_address(
221 self.sw_if_index,
222 self.local_ip6n,
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100223 self.local_ip6_prefix_len,
224 is_ipv6=1, is_add=0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000225 except AttributeError:
226 self.has_ip6_config = False
227 self.has_ip6_config = False
228
229 def unconfig(self):
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100230 """Unconfigure IPv6 and IPv4 address on the VPP interface."""
Neale Ranns177bbdc2016-11-15 09:46:51 +0000231 self.unconfig_ip4()
232 self.unconfig_ip6()
Klement Sekeraf62ae122016-10-11 11:47:09 +0200233
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000234 def set_table_ip4(self, table_id):
235 """Set the interface in a IPv4 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100236
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100237 .. note:: Must be called before configuring IP4 addresses.
238 """
239 self.ip4_table_id = table_id
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000240 self.test.vapi.sw_interface_set_table(
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100241 self.sw_if_index, 0, self.ip4_table_id)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000242
243 def set_table_ip6(self, table_id):
244 """Set the interface in a IPv6 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100245
246 .. note:: Must be called before configuring IP6 addresses.
247 """
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100248 self.ip6_table_id = table_id
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000249 self.test.vapi.sw_interface_set_table(
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100250 self.sw_if_index, 1, self.ip6_table_id)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000251
Klement Sekeraf62ae122016-10-11 11:47:09 +0200252 def disable_ipv6_ra(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100253 """Configure IPv6 RA suppress on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200254 self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
255
Neale Ranns75152282017-01-09 01:00:45 -0800256 def ip6_ra_config(self, suppress=0, send_unicast=0):
257 """Configure IPv6 RA suppress on the VPP interface."""
258 self.test.vapi.ip6_sw_interface_ra_config(self.sw_if_index,
259 suppress,
260 send_unicast)
261
Klement Sekeraf62ae122016-10-11 11:47:09 +0200262 def admin_up(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100263 """Put interface ADMIN-UP."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200264 self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=1)
265
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100266 def admin_down(self):
267 """Put interface ADMIN-down."""
268 self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=0)
269
Neale Ranns75152282017-01-09 01:00:45 -0800270 def ip6_enable(self):
271 """IPv6 Enable interface"""
272 self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index, enable=1)
273
274 def ip6_disable(self):
275 """Put interface ADMIN-DOWN."""
276 self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index, enable=0)
277
Klement Sekeraf62ae122016-10-11 11:47:09 +0200278 def add_sub_if(self, sub_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100279 """Register a sub-interface with this interface.
Klement Sekeraf62ae122016-10-11 11:47:09 +0200280
281 :param sub_if: sub-interface
Klement Sekeraf62ae122016-10-11 11:47:09 +0200282 """
283 if not hasattr(self, 'sub_if'):
284 self.sub_if = sub_if
285 else:
286 if isinstance(self.sub_if, list):
287 self.sub_if.append(sub_if)
288 else:
289 self.sub_if = sub_if
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000290
291 def enable_mpls(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100292 """Enable MPLS on the VPP interface."""
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000293 self.test.vapi.sw_interface_enable_disable_mpls(
294 self.sw_if_index)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100295
296 def is_ip4_entry_in_fib_dump(self, dump):
297 for i in dump:
298 if i.address == self.local_ip4n and \
299 i.address_length == self.local_ip4_prefix_len and \
300 i.table_id == self.ip4_table_id:
301 return True
302 return False