blob: 856a5cc2183b1162e2ec31c73c6f529dbea9163e [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
Matej Klotton86d87c42016-11-11 11:38:55 +0100198 def configure_ipv4_neighbors(self):
199 """For every remote host assign neighbor's MAC to IPv4 addresses."""
Matej Klotton0178d522016-11-04 11:11:44 +0100200 for host in self._remote_hosts:
201 macn = host.mac.replace(":", "").decode('hex')
202 ipn = host.ip4n
203 self.test.vapi.ip_neighbor_add_del(self.sw_if_index, macn, ipn)
204
Klement Sekeraf62ae122016-10-11 11:47:09 +0200205 def config_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100206 """Configure IPv6 address on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200207 self.test.vapi.sw_interface_add_del_address(
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100208 self.sw_if_index, self._local_ip6n, self.local_ip6_prefix_len,
209 is_ipv6=1)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000210 self.has_ip6_config = True
211
212 def unconfig_ip6(self):
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100213 """Remove IPv6 address on the VPP interface."""
Neale Ranns177bbdc2016-11-15 09:46:51 +0000214 try:
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100215 if self.has_ip6_config:
Neale Ranns177bbdc2016-11-15 09:46:51 +0000216 self.test.vapi.sw_interface_add_del_address(
217 self.sw_if_index,
218 self.local_ip6n,
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100219 self.local_ip6_prefix_len,
220 is_ipv6=1, is_add=0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000221 except AttributeError:
222 self.has_ip6_config = False
223 self.has_ip6_config = False
224
225 def unconfig(self):
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100226 """Unconfigure IPv6 and IPv4 address on the VPP interface."""
Neale Ranns177bbdc2016-11-15 09:46:51 +0000227 self.unconfig_ip4()
228 self.unconfig_ip6()
Klement Sekeraf62ae122016-10-11 11:47:09 +0200229
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000230 def set_table_ip4(self, table_id):
231 """Set the interface in a IPv4 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100232
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100233 .. note:: Must be called before configuring IP4 addresses.
234 """
235 self.ip4_table_id = table_id
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000236 self.test.vapi.sw_interface_set_table(
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100237 self.sw_if_index, 0, self.ip4_table_id)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000238
239 def set_table_ip6(self, table_id):
240 """Set the interface in a IPv6 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100241
242 .. note:: Must be called before configuring IP6 addresses.
243 """
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100244 self.ip6_table_id = table_id
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000245 self.test.vapi.sw_interface_set_table(
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100246 self.sw_if_index, 1, self.ip6_table_id)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000247
Klement Sekeraf62ae122016-10-11 11:47:09 +0200248 def disable_ipv6_ra(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100249 """Configure IPv6 RA suppress on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200250 self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
251
Neale Ranns75152282017-01-09 01:00:45 -0800252 def ip6_ra_config(self, suppress=0, send_unicast=0):
253 """Configure IPv6 RA suppress on the VPP interface."""
254 self.test.vapi.ip6_sw_interface_ra_config(self.sw_if_index,
255 suppress,
256 send_unicast)
257
Klement Sekeraf62ae122016-10-11 11:47:09 +0200258 def admin_up(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100259 """Put interface ADMIN-UP."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200260 self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=1)
261
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100262 def admin_down(self):
263 """Put interface ADMIN-down."""
264 self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=0)
265
Neale Ranns75152282017-01-09 01:00:45 -0800266 def ip6_enable(self):
267 """IPv6 Enable interface"""
268 self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index, enable=1)
269
270 def ip6_disable(self):
271 """Put interface ADMIN-DOWN."""
272 self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index, enable=0)
273
Klement Sekeraf62ae122016-10-11 11:47:09 +0200274 def add_sub_if(self, sub_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100275 """Register a sub-interface with this interface.
Klement Sekeraf62ae122016-10-11 11:47:09 +0200276
277 :param sub_if: sub-interface
Klement Sekeraf62ae122016-10-11 11:47:09 +0200278 """
279 if not hasattr(self, 'sub_if'):
280 self.sub_if = sub_if
281 else:
282 if isinstance(self.sub_if, list):
283 self.sub_if.append(sub_if)
284 else:
285 self.sub_if = sub_if
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000286
287 def enable_mpls(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100288 """Enable MPLS on the VPP interface."""
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000289 self.test.vapi.sw_interface_enable_disable_mpls(
290 self.sw_if_index)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100291
292 def is_ip4_entry_in_fib_dump(self, dump):
293 for i in dump:
294 if i.address == self.local_ip4n and \
295 i.address_length == self.local_ip4_prefix_len and \
296 i.table_id == self.ip4_table_id:
297 return True
298 return False