blob: 024aeb5f8a3b0c86ec9f7081614903bf7447fcad [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
Klement Sekeraf62ae122016-10-11 11:47:09 +02004
5class VppInterface(object):
Matej Klotton86d87c42016-11-11 11:38:55 +01006 """Generic VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +02007 __metaclass__ = ABCMeta
8
9 @property
10 def sw_if_index(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010011 """Interface index assigned by VPP."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020012 return self._sw_if_index
13
14 @property
15 def remote_mac(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010016 """MAC-address of the remote interface "connected" to this interface."""
Matej Klotton0178d522016-11-04 11:11:44 +010017 return self._remote_hosts[0].mac
Klement Sekeraf62ae122016-10-11 11:47:09 +020018
19 @property
20 def local_mac(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010021 """MAC-address of the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020022 return self._local_mac
23
24 @property
25 def local_ip4(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010026 """Local IPv4 address on VPP interface (string)."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020027 return self._local_ip4
28
29 @property
30 def local_ip4n(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010031 """Local IPv4 address - raw, suitable as API parameter."""
Matej Klotton0178d522016-11-04 11:11:44 +010032 return socket.inet_pton(socket.AF_INET, self._local_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +020033
34 @property
35 def remote_ip4(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010036 """IPv4 address of remote peer "connected" to this interface."""
Matej Klotton0178d522016-11-04 11:11:44 +010037 return self._remote_hosts[0].ip4
Klement Sekeraf62ae122016-10-11 11:47:09 +020038
39 @property
40 def remote_ip4n(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010041 """IPv4 address of remote peer - raw, suitable as API parameter."""
Matej Klotton0178d522016-11-04 11:11:44 +010042 return socket.inet_pton(socket.AF_INET, self.remote_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +020043
44 @property
45 def local_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010046 """Local IPv6 address on VPP interface (string)."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020047 return self._local_ip6
48
49 @property
50 def local_ip6n(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010051 """Local IPv6 address - raw, suitable as API parameter."""
Matej Klotton0178d522016-11-04 11:11:44 +010052 return socket.inet_pton(socket.AF_INET6, self.local_ip6)
Klement Sekeraf62ae122016-10-11 11:47:09 +020053
54 @property
55 def remote_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010056 """IPv6 address of remote peer "connected" to this interface."""
Matej Klotton0178d522016-11-04 11:11:44 +010057 return self._remote_hosts[0].ip6
Klement Sekeraf62ae122016-10-11 11:47:09 +020058
59 @property
60 def remote_ip6n(self):
61 """IPv6 address of remote peer - raw, suitable as API parameter"""
Matej Klotton0178d522016-11-04 11:11:44 +010062 return socket.inet_pton(socket.AF_INET6, self.remote_ip6)
Klement Sekeraf62ae122016-10-11 11:47:09 +020063
64 @property
65 def name(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010066 """Name of the interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020067 return self._name
68
69 @property
70 def dump(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010071 """RAW result of sw_interface_dump for this interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020072 return self._dump
73
74 @property
75 def test(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010076 """Test case creating this interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020077 return self._test
78
Matej Klotton0178d522016-11-04 11:11:44 +010079 @property
80 def remote_hosts(self):
81 """Remote hosts list"""
82 return self._remote_hosts
83
84 @remote_hosts.setter
85 def remote_hosts(self, value):
Matej Klotton86d87c42016-11-11 11:38:55 +010086 """
87 :param list value: List of remote hosts.
88 """
Matej Klotton0178d522016-11-04 11:11:44 +010089 self._remote_hosts = value
Matej Klotton86d87c42016-11-11 11:38:55 +010090 self._hosts_by_mac = {}
91 self._hosts_by_ip4 = {}
92 self._hosts_by_ip6 = {}
93 for host in self._remote_hosts:
94 self._hosts_by_mac[host.mac] = host
95 self._hosts_by_ip4[host.ip4] = host
96 self._hosts_by_ip6[host.ip6] = host
Matej Klotton0178d522016-11-04 11:11:44 +010097
98 def host_by_mac(self, mac):
Matej Klotton86d87c42016-11-11 11:38:55 +010099 """
Matej Klottonc5bf07f2016-11-23 15:27:17 +0100100 :param mac: MAC address to find host by.
Matej Klotton86d87c42016-11-11 11:38:55 +0100101 :return: Host object assigned to interface.
102 """
Matej Klotton0178d522016-11-04 11:11:44 +0100103 return self._hosts_by_mac[mac]
104
105 def host_by_ip4(self, ip):
Matej Klotton86d87c42016-11-11 11:38:55 +0100106 """
107 :param ip: IPv4 address to find host by.
108 :return: Host object assigned to interface.
109 """
Matej Klotton0178d522016-11-04 11:11:44 +0100110 return self._hosts_by_ip4[ip]
111
112 def host_by_ip6(self, ip):
Matej Klotton86d87c42016-11-11 11:38:55 +0100113 """
114 :param ip: IPv6 address to find host by.
115 :return: Host object assigned to interface.
116 """
Matej Klotton0178d522016-11-04 11:11:44 +0100117 return self._hosts_by_ip6[ip]
118
119 def generate_remote_hosts(self, count=1):
Matej Klotton86d87c42016-11-11 11:38:55 +0100120 """Generate and add remote hosts for the interface.
121
122 :param int count: Number of generated remote hosts.
123 """
Matej Klotton0178d522016-11-04 11:11:44 +0100124 self._remote_hosts = []
125 self._hosts_by_mac = {}
126 self._hosts_by_ip4 = {}
127 self._hosts_by_ip6 = {}
Klement Sekera7bb873a2016-11-18 07:38:42 +0100128 for i in range(
129 2, count + 2): # 0: network address, 1: local vpp address
Matej Klotton0178d522016-11-04 11:11:44 +0100130 mac = "02:%02x:00:00:ff:%02x" % (self.sw_if_index, i)
131 ip4 = "172.16.%u.%u" % (self.sw_if_index, i)
132 ip6 = "fd01:%04x::%04x" % (self.sw_if_index, i)
133 host = Host(mac, ip4, ip6)
134 self._remote_hosts.append(host)
135 self._hosts_by_mac[mac] = host
136 self._hosts_by_ip4[ip4] = host
137 self._hosts_by_ip6[ip6] = host
138
Matej Klottonc5bf07f2016-11-23 15:27:17 +0100139 @abstractmethod
140 def __init__(self, test):
141 self._test = test
142
143 self._remote_hosts = []
144 self._hosts_by_mac = {}
145 self._hosts_by_ip4 = {}
146 self._hosts_by_ip6 = {}
Matej Klotton0178d522016-11-04 11:11:44 +0100147
148 self.generate_remote_hosts()
Klement Sekeraf62ae122016-10-11 11:47:09 +0200149
150 self._local_ip4 = "172.16.%u.1" % self.sw_if_index
151 self._local_ip4n = socket.inet_pton(socket.AF_INET, self.local_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200152
Matej Klotton0178d522016-11-04 11:11:44 +0100153 self._local_ip6 = "fd01:%04x::1" % self.sw_if_index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200154 self._local_ip6n = socket.inet_pton(socket.AF_INET6, self.local_ip6)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200155
156 r = self.test.vapi.sw_interface_dump()
157 for intf in r:
158 if intf.sw_if_index == self.sw_if_index:
159 self._name = intf.interface_name.split(b'\0', 1)[0]
Klement Sekera7bb873a2016-11-18 07:38:42 +0100160 self._local_mac =\
161 ':'.join(intf.l2_address.encode('hex')[i:i + 2]
162 for i in range(0, 12, 2))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200163 self._dump = intf
164 break
165 else:
166 raise Exception(
167 "Could not find interface with sw_if_index %d "
168 "in interface dump %s" %
169 (self.sw_if_index, repr(r)))
170
Klement Sekeraf62ae122016-10-11 11:47:09 +0200171 def config_ip4(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100172 """Configure IPv4 address on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200173 addr = self.local_ip4n
174 addr_len = 24
175 self.test.vapi.sw_interface_add_del_address(
176 self.sw_if_index, addr, addr_len)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000177 self.has_ip4_config = True
178
179 def unconfig_ip4(self):
180 """Remove IPv4 address on the VPP interface"""
181 try:
182 if (self.has_ip4_config):
183 self.test.vapi.sw_interface_add_del_address(
184 self.sw_if_index,
185 self.local_ip4n,
186 24, is_add=0)
187 except AttributeError:
188 self.has_ip4_config = False
189 self.has_ip4_config = False
Klement Sekeraf62ae122016-10-11 11:47:09 +0200190
Matej Klotton86d87c42016-11-11 11:38:55 +0100191 def configure_ipv4_neighbors(self):
192 """For every remote host assign neighbor's MAC to IPv4 addresses."""
Matej Klotton0178d522016-11-04 11:11:44 +0100193 for host in self._remote_hosts:
194 macn = host.mac.replace(":", "").decode('hex')
195 ipn = host.ip4n
196 self.test.vapi.ip_neighbor_add_del(self.sw_if_index, macn, ipn)
197
Klement Sekeraf62ae122016-10-11 11:47:09 +0200198 def config_ip6(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100199 """Configure IPv6 address on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200200 addr = self._local_ip6n
201 addr_len = 64
202 self.test.vapi.sw_interface_add_del_address(
203 self.sw_if_index, addr, addr_len, is_ipv6=1)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000204 self.has_ip6_config = True
205
206 def unconfig_ip6(self):
207 """Remove IPv6 address on the VPP interface"""
208 try:
209 if (self.has_ip6_config):
210 self.test.vapi.sw_interface_add_del_address(
211 self.sw_if_index,
212 self.local_ip6n,
213 64, is_ipv6=1, is_add=0)
214 except AttributeError:
215 self.has_ip6_config = False
216 self.has_ip6_config = False
217
218 def unconfig(self):
219 """Unconfigure IPv6 and IPv4 address on the VPP interface"""
220 self.unconfig_ip4()
221 self.unconfig_ip6()
Klement Sekeraf62ae122016-10-11 11:47:09 +0200222
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000223 def set_table_ip4(self, table_id):
224 """Set the interface in a IPv4 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100225
226 .. note:: Must be called before configuring IP4 addresses."""
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000227 self.test.vapi.sw_interface_set_table(
228 self.sw_if_index, 0, table_id)
229
230 def set_table_ip6(self, table_id):
231 """Set the interface in a IPv6 Table.
Matej Klotton86d87c42016-11-11 11:38:55 +0100232
233 .. note:: Must be called before configuring IP6 addresses.
234 """
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000235 self.test.vapi.sw_interface_set_table(
236 self.sw_if_index, 1, table_id)
237
Klement Sekeraf62ae122016-10-11 11:47:09 +0200238 def disable_ipv6_ra(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100239 """Configure IPv6 RA suppress on the VPP interface."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200240 self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
241
Klement Sekeraf62ae122016-10-11 11:47:09 +0200242 def admin_up(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100243 """Put interface ADMIN-UP."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200244 self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=1)
245
246 def add_sub_if(self, sub_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100247 """Register a sub-interface with this interface.
Klement Sekeraf62ae122016-10-11 11:47:09 +0200248
249 :param sub_if: sub-interface
Klement Sekeraf62ae122016-10-11 11:47:09 +0200250 """
251 if not hasattr(self, 'sub_if'):
252 self.sub_if = sub_if
253 else:
254 if isinstance(self.sub_if, list):
255 self.sub_if.append(sub_if)
256 else:
257 self.sub_if = sub_if
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000258
259 def enable_mpls(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100260 """Enable MPLS on the VPP interface."""
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000261 self.test.vapi.sw_interface_enable_disable_mpls(
262 self.sw_if_index)