blob: 53dcf3bfd340a8a8047ba3166b85b86ac910231a [file] [log] [blame]
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001#!/usr/bin/env python
2
3import unittest
Neale Rannsbc27d1b2018-02-05 01:13:38 -08004
juraj.linkes68ebc832018-11-29 09:37:08 +01005from framework import VppTestCase, VppTestRunner, is_skip_aarch64_set, \
6 is_platform_aarch64
Neale Rannsbc27d1b2018-02-05 01:13:38 -08007from vpp_object import VppObject
Neale Ranns25b04942018-04-04 09:34:50 -07008from vpp_neighbor import VppNeighbor
Neale Ranns93cc3ee2018-10-10 07:22:51 -07009from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
10 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
11from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
12 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
13from vpp_vxlan_gbp_tunnel import *
Neale Rannsc29c0af2018-11-07 04:21:12 -080014from vpp_sub_interface import VppDot1QSubint
Neale Rannsc0a93142018-09-05 15:42:26 -070015
16from vpp_ip import *
17from vpp_mac import *
Neale Rannsb4743802018-09-05 09:13:57 -070018from vpp_papi_provider import L2_PORT_TYPE
Neale Ranns93cc3ee2018-10-10 07:22:51 -070019from vpp_papi import VppEnum
Neale Rannsbc27d1b2018-02-05 01:13:38 -080020
21from scapy.packet import Raw
Neale Rannsc29c0af2018-11-07 04:21:12 -080022from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Rannsbc27d1b2018-02-05 01:13:38 -080023from scapy.layers.inet import IP, UDP
Neale Ranns25b04942018-04-04 09:34:50 -070024from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
Klement Sekerab9ef2732018-06-24 22:49:33 +020025 ICMPv6ND_NA
Neale Ranns25b04942018-04-04 09:34:50 -070026from scapy.utils6 import in6_getnsma, in6_getnsmac
Neale Ranns93cc3ee2018-10-10 07:22:51 -070027from scapy.layers.vxlan import VXLAN
Neale Rannsbc27d1b2018-02-05 01:13:38 -080028
29from socket import AF_INET, AF_INET6
Neale Ranns25b04942018-04-04 09:34:50 -070030from scapy.utils import inet_pton, inet_ntop
Klement Sekerab9ef2732018-06-24 22:49:33 +020031from util import mactobinary
Neale Rannsc29c0af2018-11-07 04:21:12 -080032from vpp_papi_provider import L2_VTR_OP
Neale Rannsbc27d1b2018-02-05 01:13:38 -080033
34
Neale Ranns93cc3ee2018-10-10 07:22:51 -070035def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
36 if ip:
37 vip = VppIpAddress(ip)
38 if mac:
39 vmac = VppMacAddress(mac)
Neale Rannsc0a93142018-09-05 15:42:26 -070040
41 eps = test.vapi.gbp_endpoint_dump()
Neale Ranns93cc3ee2018-10-10 07:22:51 -070042
Neale Rannsc0a93142018-09-05 15:42:26 -070043 for ep in eps:
Neale Ranns93cc3ee2018-10-10 07:22:51 -070044 if sw_if_index:
45 if ep.endpoint.sw_if_index != sw_if_index:
46 continue
47 if ip:
48 for eip in ep.endpoint.ips:
49 if vip == eip:
50 return True
51 if mac:
52 if vmac == ep.endpoint.mac:
Neale Rannsc0a93142018-09-05 15:42:26 -070053 return True
54 return False
55
56
Neale Ranns93cc3ee2018-10-10 07:22:51 -070057def find_gbp_vxlan(test, vni):
58 ts = test.vapi.gbp_vxlan_tunnel_dump()
59 for t in ts:
60 if t.tunnel.vni == vni:
61 return True
62 return False
63
64
Neale Rannsbc27d1b2018-02-05 01:13:38 -080065class VppGbpEndpoint(VppObject):
66 """
Mohsin Kazmi22b3b842018-04-17 19:35:42 +020067 GBP Endpoint
Neale Rannsbc27d1b2018-02-05 01:13:38 -080068 """
69
Neale Ranns25b04942018-04-04 09:34:50 -070070 @property
71 def bin_mac(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -070072 return self.vmac.bytes
73
74 @property
75 def mac(self):
76 return self.vmac.address
Neale Ranns25b04942018-04-04 09:34:50 -070077
78 @property
79 def mac(self):
80 return self.itf.remote_mac
81
Neale Rannsc0a93142018-09-05 15:42:26 -070082 @property
83 def ip4(self):
84 return self._ip4
85
86 @property
87 def fip4(self):
88 return self._fip4
89
90 @property
91 def ip6(self):
92 return self._ip6
93
94 @property
95 def fip6(self):
96 return self._fip6
97
98 @property
99 def ips(self):
100 return [self.ip4, self.ip6]
101
102 @property
103 def fips(self):
104 return [self.fip4, self.fip6]
105
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700106 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
107 flags=0,
108 tun_src="0.0.0.0",
109 tun_dst="0.0.0.0",
110 mac=True):
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800111 self._test = test
Neale Ranns25b04942018-04-04 09:34:50 -0700112 self.itf = itf
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800113 self.epg = epg
Neale Ranns25b04942018-04-04 09:34:50 -0700114 self.recirc = recirc
Neale Rannsc0a93142018-09-05 15:42:26 -0700115
116 self._ip4 = VppIpAddress(ip4)
117 self._fip4 = VppIpAddress(fip4)
118 self._ip6 = VppIpAddress(ip6)
119 self._fip6 = VppIpAddress(fip6)
120
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700121 if mac:
122 self.vmac = VppMacAddress(self.itf.remote_mac)
123 else:
124 self.vmac = VppMacAddress("00:00:00:00:00:00")
125
126 self.flags = flags
127 self.tun_src = VppIpAddress(tun_src)
128 self.tun_dst = VppIpAddress(tun_dst)
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800129
130 def add_vpp_config(self):
Neale Rannsc0a93142018-09-05 15:42:26 -0700131 res = self._test.vapi.gbp_endpoint_add(
Neale Ranns25b04942018-04-04 09:34:50 -0700132 self.itf.sw_if_index,
Neale Rannsc0a93142018-09-05 15:42:26 -0700133 [self.ip4.encode(), self.ip6.encode()],
134 self.vmac.encode(),
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700135 self.epg.epg,
136 self.flags,
137 self.tun_src.encode(),
138 self.tun_dst.encode())
Neale Rannsc0a93142018-09-05 15:42:26 -0700139 self.handle = res.handle
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800140 self._test.registry.register(self, self._test.logger)
141
142 def remove_vpp_config(self):
Neale Rannsc0a93142018-09-05 15:42:26 -0700143 self._test.vapi.gbp_endpoint_del(self.handle)
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800144
145 def __str__(self):
146 return self.object_id()
147
148 def object_id(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700149 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
150 self.itf.sw_if_index,
151 self.ip4.address,
152 self.epg.epg)
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800153
154 def query_vpp_config(self):
Neale Rannsc0a93142018-09-05 15:42:26 -0700155 return find_gbp_endpoint(self._test,
156 self.itf.sw_if_index,
157 self.ip4.address)
Neale Ranns25b04942018-04-04 09:34:50 -0700158
159
160class VppGbpRecirc(VppObject):
161 """
Mohsin Kazmi22b3b842018-04-17 19:35:42 +0200162 GBP Recirculation Interface
Neale Ranns25b04942018-04-04 09:34:50 -0700163 """
164
165 def __init__(self, test, epg, recirc, is_ext=False):
166 self._test = test
167 self.recirc = recirc
168 self.epg = epg
169 self.is_ext = is_ext
170
171 def add_vpp_config(self):
172 self._test.vapi.gbp_recirc_add_del(
173 1,
174 self.recirc.sw_if_index,
175 self.epg.epg,
176 self.is_ext)
177 self._test.registry.register(self, self._test.logger)
178
179 def remove_vpp_config(self):
180 self._test.vapi.gbp_recirc_add_del(
181 0,
182 self.recirc.sw_if_index,
183 self.epg.epg,
184 self.is_ext)
185
186 def __str__(self):
187 return self.object_id()
188
189 def object_id(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700190 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
Neale Ranns25b04942018-04-04 09:34:50 -0700191
192 def query_vpp_config(self):
193 rs = self._test.vapi.gbp_recirc_dump()
194 for r in rs:
195 if r.recirc.sw_if_index == self.recirc.sw_if_index:
196 return True
197 return False
198
199
Neale Rannsb6a47952018-11-21 05:44:35 -0800200class VppGbpExtItf(VppObject):
201 """
202 GBP ExtItfulation Interface
203 """
204
205 def __init__(self, test, itf, bd, rd):
206 self._test = test
207 self.itf = itf
208 self.bd = bd
209 self.rd = rd
210
211 def add_vpp_config(self):
212 self._test.vapi.gbp_ext_itf_add_del(
213 1,
214 self.itf.sw_if_index,
215 self.bd.bd_id,
216 self.rd.rd_id)
217 self._test.registry.register(self, self._test.logger)
218
219 def remove_vpp_config(self):
220 self._test.vapi.gbp_ext_itf_add_del(
221 0,
222 self.itf.sw_if_index,
223 self.bd.bd_id,
224 self.rd.rd_id)
225
226 def __str__(self):
227 return self.object_id()
228
229 def object_id(self):
230 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
231
232 def query_vpp_config(self):
233 rs = self._test.vapi.gbp_ext_itf_dump()
234 for r in rs:
235 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
236 return True
237 return False
238
239
Neale Ranns25b04942018-04-04 09:34:50 -0700240class VppGbpSubnet(VppObject):
241 """
Mohsin Kazmi22b3b842018-04-17 19:35:42 +0200242 GBP Subnet
Neale Ranns25b04942018-04-04 09:34:50 -0700243 """
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700244 def __init__(self, test, rd, address, address_len,
245 type, sw_if_index=None, epg=None):
Neale Ranns25b04942018-04-04 09:34:50 -0700246 self._test = test
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700247 self.rd_id = rd.rd_id
Ole Troana26373b2018-10-22 14:11:45 +0200248 self.prefix = VppIpPrefix(address, address_len)
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700249 self.type = type
Neale Ranns25b04942018-04-04 09:34:50 -0700250 self.sw_if_index = sw_if_index
251 self.epg = epg
252
253 def add_vpp_config(self):
254 self._test.vapi.gbp_subnet_add_del(
255 1,
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700256 self.rd_id,
Ole Troana26373b2018-10-22 14:11:45 +0200257 self.prefix.encode(),
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700258 self.type,
Neale Ranns25b04942018-04-04 09:34:50 -0700259 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
Neale Rannsc0a93142018-09-05 15:42:26 -0700260 epg_id=self.epg if self.epg else 0xffff)
Neale Ranns25b04942018-04-04 09:34:50 -0700261 self._test.registry.register(self, self._test.logger)
262
263 def remove_vpp_config(self):
264 self._test.vapi.gbp_subnet_add_del(
265 0,
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700266 self.rd_id,
267 self.prefix.encode(),
268 self.type)
Neale Ranns25b04942018-04-04 09:34:50 -0700269
270 def __str__(self):
271 return self.object_id()
272
273 def object_id(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700274 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
Neale Ranns25b04942018-04-04 09:34:50 -0700275
276 def query_vpp_config(self):
277 ss = self._test.vapi.gbp_subnet_dump()
278 for s in ss:
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700279 if s.subnet.rd_id == self.rd_id and \
280 s.subnet.type == self.type and \
Ole Troana26373b2018-10-22 14:11:45 +0200281 s.subnet.prefix == self.prefix:
Neale Rannsc0a93142018-09-05 15:42:26 -0700282 return True
Neale Ranns25b04942018-04-04 09:34:50 -0700283 return False
284
285
286class VppGbpEndpointGroup(VppObject):
287 """
Mohsin Kazmi22b3b842018-04-17 19:35:42 +0200288 GBP Endpoint Group
Neale Ranns25b04942018-04-04 09:34:50 -0700289 """
290
291 def __init__(self, test, epg, rd, bd, uplink,
292 bvi, bvi_ip4, bvi_ip6=None):
293 self._test = test
294 self.uplink = uplink
295 self.bvi = bvi
Neale Ranns4d5b9172018-10-24 02:57:49 -0700296 self.bvi_ip4 = VppIpAddress(bvi_ip4)
297 self.bvi_ip6 = VppIpAddress(bvi_ip6)
Neale Ranns25b04942018-04-04 09:34:50 -0700298 self.epg = epg
299 self.bd = bd
300 self.rd = rd
301
302 def add_vpp_config(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700303 self._test.vapi.gbp_endpoint_group_add(
Neale Ranns25b04942018-04-04 09:34:50 -0700304 self.epg,
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700305 self.bd.bd.bd_id,
306 self.rd.rd_id,
307 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
Neale Ranns25b04942018-04-04 09:34:50 -0700308 self._test.registry.register(self, self._test.logger)
309
310 def remove_vpp_config(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700311 self._test.vapi.gbp_endpoint_group_del(
312 self.epg)
Neale Ranns25b04942018-04-04 09:34:50 -0700313
314 def __str__(self):
315 return self.object_id()
316
317 def object_id(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700318 return "gbp-endpoint-group:[%d]" % (self.epg)
Neale Ranns25b04942018-04-04 09:34:50 -0700319
320 def query_vpp_config(self):
321 epgs = self._test.vapi.gbp_endpoint_group_dump()
322 for epg in epgs:
323 if epg.epg.epg_id == self.epg:
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800324 return True
325 return False
326
327
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700328class VppGbpBridgeDomain(VppObject):
329 """
330 GBP Bridge Domain
331 """
332
Neale Rannsc29c0af2018-11-07 04:21:12 -0800333 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700334 self._test = test
335 self.bvi = bvi
336 self.uu_flood = uu_flood
337 self.bd = bd
338
Neale Rannsc29c0af2018-11-07 04:21:12 -0800339 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
340 if (learn):
341 self.learn = e.GBP_BD_API_FLAG_NONE
342 else:
343 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
344
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700345 def add_vpp_config(self):
346 self._test.vapi.gbp_bridge_domain_add(
347 self.bd.bd_id,
Neale Rannsc29c0af2018-11-07 04:21:12 -0800348 self.learn,
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700349 self.bvi.sw_if_index,
350 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
351 self._test.registry.register(self, self._test.logger)
352
353 def remove_vpp_config(self):
354 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
355
356 def __str__(self):
357 return self.object_id()
358
359 def object_id(self):
360 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
361
362 def query_vpp_config(self):
363 bds = self._test.vapi.gbp_bridge_domain_dump()
364 for bd in bds:
365 if bd.bd.bd_id == self.bd.bd_id:
366 return True
367 return False
368
369
370class VppGbpRouteDomain(VppObject):
371 """
372 GBP Route Domain
373 """
374
375 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
376 self._test = test
377 self.rd_id = rd_id
378 self.t4 = t4
379 self.t6 = t6
380 self.ip4_uu = ip4_uu
381 self.ip6_uu = ip6_uu
382
383 def add_vpp_config(self):
384 self._test.vapi.gbp_route_domain_add(
385 self.rd_id,
386 self.t4.table_id,
387 self.t6.table_id,
388 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
389 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
390 self._test.registry.register(self, self._test.logger)
391
392 def remove_vpp_config(self):
393 self._test.vapi.gbp_route_domain_del(self.rd_id)
394
395 def __str__(self):
396 return self.object_id()
397
398 def object_id(self):
399 return "gbp-route-domain:[%d]" % (self.rd_id)
400
401 def query_vpp_config(self):
402 rds = self._test.vapi.gbp_route_domain_dump()
403 for rd in rds:
404 if rd.rd.rd_id == self.rd_id:
405 return True
406 return False
407
408
Neale Ranns13a08cc2018-11-07 09:25:54 -0800409class VppGbpContractNextHop():
410 def __init__(self, mac, bd, ip, rd):
411 self.mac = mac
412 self.ip = ip
413 self.bd = bd
414 self.rd = rd
415
416 def encode(self):
417 return {'ip': self.ip.encode(),
418 'mac': self.mac.encode(),
419 'bd_id': self.bd.bd.bd_id,
420 'rd_id': self.rd.rd_id}
421
422
423class VppGbpContractRule():
Mohsin Kazmid40c3e62018-11-21 10:46:57 +0100424 def __init__(self, action, hash_mode, nhs=[]):
Neale Ranns13a08cc2018-11-07 09:25:54 -0800425 self.action = action
Mohsin Kazmid40c3e62018-11-21 10:46:57 +0100426 self.hash_mode = hash_mode
Neale Ranns13a08cc2018-11-07 09:25:54 -0800427 self.nhs = nhs
Neale Ranns13a08cc2018-11-07 09:25:54 -0800428
429 def encode(self):
430 nhs = []
431 for nh in self.nhs:
432 nhs.append(nh.encode())
433 while len(nhs) < 8:
434 nhs.append({})
435 return {'action': self.action,
436 'nh_set': {
437 'hash_mode': self.hash_mode,
438 'n_nhs': len(self.nhs),
439 'nhs': nhs}}
440
441
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800442class VppGbpContract(VppObject):
443 """
Mohsin Kazmi22b3b842018-04-17 19:35:42 +0200444 GBP Contract
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800445 """
446
Neale Ranns13a08cc2018-11-07 09:25:54 -0800447 def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800448 self._test = test
449 self.acl_index = acl_index
450 self.src_epg = src_epg
451 self.dst_epg = dst_epg
Neale Ranns13a08cc2018-11-07 09:25:54 -0800452 self.rules = rules
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800453
454 def add_vpp_config(self):
Neale Ranns13a08cc2018-11-07 09:25:54 -0800455 rules = []
456 for r in self.rules:
457 rules.append(r.encode())
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800458 self._test.vapi.gbp_contract_add_del(
459 1,
460 self.src_epg,
461 self.dst_epg,
Neale Ranns13a08cc2018-11-07 09:25:54 -0800462 self.acl_index,
463 rules)
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800464 self._test.registry.register(self, self._test.logger)
465
466 def remove_vpp_config(self):
467 self._test.vapi.gbp_contract_add_del(
468 0,
469 self.src_epg,
470 self.dst_epg,
Neale Ranns13a08cc2018-11-07 09:25:54 -0800471 self.acl_index,
472 [])
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800473
474 def __str__(self):
475 return self.object_id()
476
477 def object_id(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700478 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800479 self.dst_epg,
480 self.acl_index)
481
482 def query_vpp_config(self):
Neale Ranns25b04942018-04-04 09:34:50 -0700483 cs = self._test.vapi.gbp_contract_dump()
484 for c in cs:
485 if c.contract.src_epg == self.src_epg \
486 and c.contract.dst_epg == self.dst_epg:
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800487 return True
488 return False
489
490
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700491class VppGbpVxlanTunnel(VppInterface):
492 """
493 GBP VXLAN tunnel
494 """
495
496 def __init__(self, test, vni, bd_rd_id, mode):
497 super(VppGbpVxlanTunnel, self).__init__(test)
498 self._test = test
499 self.vni = vni
500 self.bd_rd_id = bd_rd_id
501 self.mode = mode
502
503 def add_vpp_config(self):
504 r = self._test.vapi.gbp_vxlan_tunnel_add(
505 self.vni,
506 self.bd_rd_id,
507 self.mode)
508 self.set_sw_if_index(r.sw_if_index)
509 self._test.registry.register(self, self._test.logger)
510
511 def remove_vpp_config(self):
512 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
513
514 def __str__(self):
515 return self.object_id()
516
517 def object_id(self):
518 return "gbp-vxlan:%d" % (self.vni)
519
520 def query_vpp_config(self):
521 return find_gbp_vxlan(self._test, self.vni)
522
523
Mohsin Kazmi22b3b842018-04-17 19:35:42 +0200524class VppGbpAcl(VppObject):
525 """
526 GBP Acl
527 """
528
529 def __init__(self, test):
530 self._test = test
531 self.acl_index = 4294967295
532
533 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
534 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
535 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
536 dport_from=0, dport_to=65535):
537 if proto == -1 or proto == 0:
538 sport_to = 0
539 dport_to = sport_to
540 elif proto == 1 or proto == 58:
541 sport_to = 255
542 dport_to = sport_to
543 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
544 'srcport_or_icmptype_first': sport_from,
545 'srcport_or_icmptype_last': sport_to,
546 'src_ip_prefix_len': s_prefix,
547 'src_ip_addr': s_ip,
548 'dstport_or_icmpcode_first': dport_from,
549 'dstport_or_icmpcode_last': dport_to,
550 'dst_ip_prefix_len': d_prefix,
551 'dst_ip_addr': d_ip})
552 return rule
553
554 def add_vpp_config(self, rules):
555
556 reply = self._test.vapi.acl_add_replace(self.acl_index,
557 r=rules,
558 tag='GBPTest')
559 self.acl_index = reply.acl_index
560 return self.acl_index
561
562 def remove_vpp_config(self):
563 self._test.vapi.acl_del(self.acl_index)
564
565 def __str__(self):
566 return self.object_id()
567
568 def object_id(self):
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700569 return "gbp-acl:[%d]" % (self.acl_index)
Mohsin Kazmi22b3b842018-04-17 19:35:42 +0200570
571 def query_vpp_config(self):
572 cs = self._test.vapi.acl_dump()
573 for c in cs:
574 if c.acl_index == self.acl_index:
575 return True
576 return False
577
578
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800579class TestGBP(VppTestCase):
580 """ GBP Test Case """
581
582 def setUp(self):
583 super(TestGBP, self).setUp()
584
Neale Ranns25b04942018-04-04 09:34:50 -0700585 self.create_pg_interfaces(range(9))
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700586 self.create_loopback_interfaces(8)
Neale Ranns25b04942018-04-04 09:34:50 -0700587
Neale Ranns4d5b9172018-10-24 02:57:49 -0700588 self.router_mac = VppMacAddress("00:11:22:33:44:55")
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800589
590 for i in self.pg_interfaces:
591 i.admin_up()
Neale Ranns25b04942018-04-04 09:34:50 -0700592 for i in self.lo_interfaces:
593 i.admin_up()
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800594
595 def tearDown(self):
596 for i in self.pg_interfaces:
Neale Ranns25b04942018-04-04 09:34:50 -0700597 i.admin_down()
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800598
599 super(TestGBP, self).tearDown()
600
Neale Ranns25b04942018-04-04 09:34:50 -0700601 def send_and_expect_bridged(self, src, tx, dst):
602 rx = self.send_and_expect(src, tx, dst)
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800603
Neale Ranns25b04942018-04-04 09:34:50 -0700604 for r in rx:
605 self.assertEqual(r[Ether].src, tx[0][Ether].src)
606 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
607 self.assertEqual(r[IP].src, tx[0][IP].src)
608 self.assertEqual(r[IP].dst, tx[0][IP].dst)
609 return rx
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800610
Neale Ranns25b04942018-04-04 09:34:50 -0700611 def send_and_expect_bridged6(self, src, tx, dst):
612 rx = self.send_and_expect(src, tx, dst)
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800613
Neale Ranns25b04942018-04-04 09:34:50 -0700614 for r in rx:
615 self.assertEqual(r[Ether].src, tx[0][Ether].src)
616 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
617 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
618 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
619 return rx
620
621 def send_and_expect_routed(self, src, tx, dst, src_mac):
622 rx = self.send_and_expect(src, tx, dst)
623
624 for r in rx:
625 self.assertEqual(r[Ether].src, src_mac)
626 self.assertEqual(r[Ether].dst, dst.remote_mac)
627 self.assertEqual(r[IP].src, tx[0][IP].src)
628 self.assertEqual(r[IP].dst, tx[0][IP].dst)
629 return rx
630
631 def send_and_expect_natted(self, src, tx, dst, src_ip):
632 rx = self.send_and_expect(src, tx, dst)
633
634 for r in rx:
635 self.assertEqual(r[Ether].src, tx[0][Ether].src)
636 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
637 self.assertEqual(r[IP].src, src_ip)
638 self.assertEqual(r[IP].dst, tx[0][IP].dst)
639 return rx
640
Neale Ranns4a6d0232018-04-24 07:45:33 -0700641 def send_and_expect_natted6(self, src, tx, dst, src_ip):
642 rx = self.send_and_expect(src, tx, dst)
643
644 for r in rx:
645 self.assertEqual(r[Ether].src, tx[0][Ether].src)
646 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
647 self.assertEqual(r[IPv6].src, src_ip)
648 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
649 return rx
650
Neale Ranns25b04942018-04-04 09:34:50 -0700651 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
652 rx = self.send_and_expect(src, tx, dst)
653
654 for r in rx:
655 self.assertEqual(r[Ether].src, tx[0][Ether].src)
656 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
657 self.assertEqual(r[IP].dst, dst_ip)
658 self.assertEqual(r[IP].src, tx[0][IP].src)
659 return rx
660
Neale Ranns4a6d0232018-04-24 07:45:33 -0700661 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
662 rx = self.send_and_expect(src, tx, dst)
663
664 for r in rx:
665 self.assertEqual(r[Ether].src, tx[0][Ether].src)
666 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
667 self.assertEqual(r[IPv6].dst, dst_ip)
668 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
669 return rx
670
Neale Ranns25b04942018-04-04 09:34:50 -0700671 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
672 rx = self.send_and_expect(src, tx, dst)
673
674 for r in rx:
Neale Ranns4d5b9172018-10-24 02:57:49 -0700675 self.assertEqual(r[Ether].src, self.router_mac.address)
Neale Ranns25b04942018-04-04 09:34:50 -0700676 self.assertEqual(r[Ether].dst, dst.remote_mac)
677 self.assertEqual(r[IP].dst, dst_ip)
678 self.assertEqual(r[IP].src, src_ip)
679 return rx
680
Neale Ranns4a6d0232018-04-24 07:45:33 -0700681 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
682 rx = self.send_and_expect(src, tx, dst)
683
684 for r in rx:
Neale Ranns4d5b9172018-10-24 02:57:49 -0700685 self.assertEqual(r[Ether].src, self.router_mac.address)
Neale Ranns4a6d0232018-04-24 07:45:33 -0700686 self.assertEqual(r[Ether].dst, dst.remote_mac)
687 self.assertEqual(r[IPv6].dst, dst_ip)
688 self.assertEqual(r[IPv6].src, src_ip)
689 return rx
690
Neale Ranns25b04942018-04-04 09:34:50 -0700691 def test_gbp(self):
692 """ Group Based Policy """
693
Neale Rannsb6a47952018-11-21 05:44:35 -0800694 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
695
Neale Rannsbc27d1b2018-02-05 01:13:38 -0800696 #
Neale Ranns25b04942018-04-04 09:34:50 -0700697 # Bridge Domains
698 #
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700699 bd1 = VppBridgeDomain(self, 1)
700 bd2 = VppBridgeDomain(self, 2)
701 bd20 = VppBridgeDomain(self, 20)
702
703 bd1.add_vpp_config()
704 bd2.add_vpp_config()
705 bd20.add_vpp_config()
706
707 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
708 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
709 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
710
711 gbd1.add_vpp_config()
712 gbd2.add_vpp_config()
713 gbd20.add_vpp_config()
714
715 #
716 # Route Domains
717 #
718 gt4 = VppIpTable(self, 0)
719 gt4.add_vpp_config()
720 gt6 = VppIpTable(self, 0, is_ip6=True)
721 gt6.add_vpp_config()
722 nt4 = VppIpTable(self, 20)
723 nt4.add_vpp_config()
724 nt6 = VppIpTable(self, 20, is_ip6=True)
725 nt6.add_vpp_config()
726
727 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
728 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
729
730 rd0.add_vpp_config()
731 rd20.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700732
733 #
734 # 3 EPGs, 2 of which share a BD.
Neale Ranns25b04942018-04-04 09:34:50 -0700735 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
736 #
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700737 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
Neale Rannsc0a93142018-09-05 15:42:26 -0700738 self.loop0,
739 "10.0.0.128",
740 "2001:10::128"),
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700741 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
Neale Rannsc0a93142018-09-05 15:42:26 -0700742 self.loop0,
743 "10.0.1.128",
744 "2001:10:1::128"),
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700745 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
Neale Rannsc0a93142018-09-05 15:42:26 -0700746 self.loop1,
747 "10.0.2.128",
748 "2001:10:2::128"),
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700749 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
Neale Rannsc0a93142018-09-05 15:42:26 -0700750 self.loop2,
751 "11.0.0.128",
752 "3001::128"),
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700753 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
Neale Rannsc0a93142018-09-05 15:42:26 -0700754 self.loop2,
755 "11.0.0.129",
756 "3001::129")]
757 recircs = [VppGbpRecirc(self, epgs[0],
758 self.loop3),
759 VppGbpRecirc(self, epgs[1],
760 self.loop4),
761 VppGbpRecirc(self, epgs[2],
762 self.loop5),
763 VppGbpRecirc(self, epgs[3],
764 self.loop6, is_ext=True),
765 VppGbpRecirc(self, epgs[4],
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700766 self.loop7, is_ext=True)]
Neale Ranns25b04942018-04-04 09:34:50 -0700767
768 epg_nat = epgs[3]
769 recirc_nat = recircs[3]
770
771 #
772 # 4 end-points, 2 in the same subnet, 3 in the same BD
773 #
Neale Rannsc0a93142018-09-05 15:42:26 -0700774 eps = [VppGbpEndpoint(self, self.pg0,
775 epgs[0], recircs[0],
776 "10.0.0.1", "11.0.0.1",
777 "2001:10::1", "3001::1"),
778 VppGbpEndpoint(self, self.pg1,
779 epgs[0], recircs[0],
780 "10.0.0.2", "11.0.0.2",
781 "2001:10::2", "3001::2"),
782 VppGbpEndpoint(self, self.pg2,
783 epgs[1], recircs[1],
784 "10.0.1.1", "11.0.0.3",
785 "2001:10:1::1", "3001::3"),
786 VppGbpEndpoint(self, self.pg3,
787 epgs[2], recircs[2],
788 "10.0.2.1", "11.0.0.4",
789 "2001:10:2::1", "3001::4")]
Neale Ranns25b04942018-04-04 09:34:50 -0700790
791 #
792 # Config related to each of the EPGs
793 #
794 for epg in epgs:
795 # IP config on the BVI interfaces
796 if epg != epgs[1] and epg != epgs[4]:
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700797 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
798 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
799 self.vapi.sw_interface_set_mac_address(
800 epg.bvi.sw_if_index,
801 self.router_mac.bytes)
Neale Ranns25b04942018-04-04 09:34:50 -0700802
803 # The BVIs are NAT inside interfaces
804 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
805 is_inside=1,
806 is_add=1)
Neale Ranns4a6d0232018-04-24 07:45:33 -0700807 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
808 is_inside=1,
809 is_add=1)
Neale Ranns25b04942018-04-04 09:34:50 -0700810
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700811 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
812 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
813 if_ip4.add_vpp_config()
814 if_ip6.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700815
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700816 # EPG uplink interfaces in the RD
817 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
818 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700819
820 # add the BD ARP termination entry for BVI IP
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700821 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
822 self.router_mac.address,
823 epg.bvi_ip4)
824 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
825 self.router_mac.address,
826 epg.bvi_ip6)
827 epg.bd_arp_ip4.add_vpp_config()
828 epg.bd_arp_ip6.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700829
830 # EPG in VPP
831 epg.add_vpp_config()
832
833 for recirc in recircs:
834 # EPG's ingress recirculation interface maps to its RD
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700835 VppIpInterfaceBind(self, recirc.recirc,
836 recirc.epg.rd.t4).add_vpp_config()
837 VppIpInterfaceBind(self, recirc.recirc,
838 recirc.epg.rd.t6).add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700839
Neale Ranns4a6d0232018-04-24 07:45:33 -0700840 self.vapi.nat44_interface_add_del_feature(
841 recirc.recirc.sw_if_index,
842 is_inside=0,
843 is_add=1)
844 self.vapi.nat66_add_del_interface(
845 recirc.recirc.sw_if_index,
846 is_inside=0,
847 is_add=1)
Neale Ranns25b04942018-04-04 09:34:50 -0700848
849 recirc.add_vpp_config()
850
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700851 for recirc in recircs:
852 self.assertTrue(find_bridge_domain_port(self,
853 recirc.epg.bd.bd.bd_id,
854 recirc.recirc.sw_if_index))
855
Neale Ranns25b04942018-04-04 09:34:50 -0700856 for ep in eps:
857 self.pg_enable_capture(self.pg_interfaces)
858 self.pg_start()
859 #
860 # routes to the endpoints. We need these since there are no
861 # adj-fibs due to the fact the the BVI address has /32 and
862 # the subnet is not attached.
863 #
Neale Rannsc0a93142018-09-05 15:42:26 -0700864 for (ip, fip) in zip(ep.ips, ep.fips):
Neale Rannsc0a93142018-09-05 15:42:26 -0700865 # Add static mappings for each EP from the 10/8 to 11/8 network
866 if ip.af == AF_INET:
867 self.vapi.nat44_add_del_static_mapping(ip.bytes,
868 fip.bytes,
869 vrf_id=0,
870 addr_only=1)
871 else:
872 self.vapi.nat66_add_del_static_mapping(ip.bytes,
873 fip.bytes,
874 vrf_id=0)
Neale Ranns25b04942018-04-04 09:34:50 -0700875
Neale Ranns25b04942018-04-04 09:34:50 -0700876 # VPP EP create ...
877 ep.add_vpp_config()
878
Neale Rannsc0a93142018-09-05 15:42:26 -0700879 self.logger.info(self.vapi.cli("sh gbp endpoint"))
Neale Ranns25b04942018-04-04 09:34:50 -0700880
Neale Rannsc0a93142018-09-05 15:42:26 -0700881 # ... results in a Gratuitous ARP/ND on the EPG's uplink
882 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
883
884 for ii, ip in enumerate(ep.ips):
885 p = rx[ii]
886
887 if ip.is_ip6:
888 self.assertTrue(p.haslayer(ICMPv6ND_NA))
889 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
890 else:
891 self.assertTrue(p.haslayer(ARP))
892 self.assertEqual(p[ARP].psrc, ip.address)
893 self.assertEqual(p[ARP].pdst, ip.address)
Neale Ranns25b04942018-04-04 09:34:50 -0700894
895 # add the BD ARP termination entry for floating IP
Neale Rannsc0a93142018-09-05 15:42:26 -0700896 for fip in ep.fips:
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700897 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
898 ba.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700899
Neale Rannsc0a93142018-09-05 15:42:26 -0700900 # floating IPs route via EPG recirc
901 r = VppIpRoute(self, fip.address, fip.length,
902 [VppRoutePath(fip.address,
903 ep.recirc.recirc.sw_if_index,
904 is_dvr=1,
905 proto=fip.dpo_proto)],
906 table_id=20,
907 is_ip6=fip.is_ip6)
908 r.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700909
910 # L2 FIB entries in the NAT EPG BD to bridge the packets from
911 # the outside direct to the internal EPG
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700912 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
913 ep.recirc.recirc, bvi_mac=0)
914 lf.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -0700915
916 #
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700917 # ARP packets for unknown IP are sent to the EPG uplink
Neale Ranns25b04942018-04-04 09:34:50 -0700918 #
919 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
920 src=self.pg0.remote_mac) /
921 ARP(op="who-has",
922 hwdst="ff:ff:ff:ff:ff:ff",
923 hwsrc=self.pg0.remote_mac,
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700924 pdst="10.0.0.88",
925 psrc="10.0.0.99"))
Neale Ranns25b04942018-04-04 09:34:50 -0700926
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700927 self.vapi.cli("clear trace")
928 self.pg0.add_stream(pkt_arp)
929
930 self.pg_enable_capture(self.pg_interfaces)
931 self.pg_start()
932
933 rxd = epgs[0].uplink.get_capture(1)
Neale Ranns25b04942018-04-04 09:34:50 -0700934
935 #
936 # ARP/ND packets get a response
937 #
938 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
939 src=self.pg0.remote_mac) /
940 ARP(op="who-has",
941 hwdst="ff:ff:ff:ff:ff:ff",
942 hwsrc=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -0700943 pdst=epgs[0].bvi_ip4.address,
Neale Rannsc0a93142018-09-05 15:42:26 -0700944 psrc=eps[0].ip4.address))
Neale Ranns25b04942018-04-04 09:34:50 -0700945
946 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
947
Neale Rannsc0a93142018-09-05 15:42:26 -0700948 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
Neale Ranns25b04942018-04-04 09:34:50 -0700949 d = inet_ntop(AF_INET6, nsma)
Neale Ranns93cc3ee2018-10-10 07:22:51 -0700950 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
951 src=self.pg0.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -0700952 IPv6(dst=d, src=eps[0].ip6.address) /
Neale Ranns4d5b9172018-10-24 02:57:49 -0700953 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
Neale Ranns25b04942018-04-04 09:34:50 -0700954 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
955 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
956
957 #
958 # broadcast packets are flooded
959 #
960 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
961 src=self.pg0.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -0700962 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
Neale Ranns25b04942018-04-04 09:34:50 -0700963 UDP(sport=1234, dport=1234) /
964 Raw('\xa5' * 100))
965
966 self.vapi.cli("clear trace")
967 self.pg0.add_stream(pkt_bcast)
968
969 self.pg_enable_capture(self.pg_interfaces)
970 self.pg_start()
971
972 rxd = eps[1].itf.get_capture(1)
973 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
974 rxd = epgs[0].uplink.get_capture(1)
975 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
976
977 #
978 # packets to non-local L3 destinations dropped
979 #
980 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -0700981 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -0700982 IP(src=eps[0].ip4.address,
983 dst="10.0.0.99") /
Neale Ranns25b04942018-04-04 09:34:50 -0700984 UDP(sport=1234, dport=1234) /
985 Raw('\xa5' * 100))
986 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -0700987 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -0700988 IP(src=eps[0].ip4.address,
989 dst="10.0.1.99") /
Neale Ranns25b04942018-04-04 09:34:50 -0700990 UDP(sport=1234, dport=1234) /
991 Raw('\xa5' * 100))
992
993 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
994
995 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -0700996 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -0700997 IPv6(src=eps[0].ip6.address,
998 dst="2001:10::99") /
Neale Ranns25b04942018-04-04 09:34:50 -0700999 UDP(sport=1234, dport=1234) /
1000 Raw('\xa5' * 100))
1001 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1002
1003 #
1004 # Add the subnet routes
1005 #
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001006 s41 = VppGbpSubnet(
1007 self, rd0, "10.0.0.0", 24,
1008 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1009 s42 = VppGbpSubnet(
1010 self, rd0, "10.0.1.0", 24,
1011 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1012 s43 = VppGbpSubnet(
1013 self, rd0, "10.0.2.0", 24,
1014 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1015 s61 = VppGbpSubnet(
1016 self, rd0, "2001:10::1", 64,
1017 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1018 s62 = VppGbpSubnet(
1019 self, rd0, "2001:10:1::1", 64,
1020 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1021 s63 = VppGbpSubnet(
1022 self, rd0, "2001:10:2::1", 64,
1023 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
Neale Ranns25b04942018-04-04 09:34:50 -07001024 s41.add_vpp_config()
1025 s42.add_vpp_config()
1026 s43.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -07001027 s61.add_vpp_config()
1028 s62.add_vpp_config()
1029 s63.add_vpp_config()
1030
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001031 self.send_and_expect_bridged(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001032 pkt_intra_epg_220_ip4 * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001033 eps[0].epg.uplink)
1034 self.send_and_expect_bridged(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001035 pkt_inter_epg_222_ip4 * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001036 eps[0].epg.uplink)
1037 self.send_and_expect_bridged6(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001038 pkt_inter_epg_222_ip6 * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001039 eps[0].epg.uplink)
Neale Ranns25b04942018-04-04 09:34:50 -07001040
1041 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1042 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1043 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1044 self.logger.info(self.vapi.cli("sh gbp recirc"))
1045 self.logger.info(self.vapi.cli("sh int"))
1046 self.logger.info(self.vapi.cli("sh int addr"))
1047 self.logger.info(self.vapi.cli("sh int feat loop6"))
1048 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1049 self.logger.info(self.vapi.cli("sh int feat loop3"))
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001050 self.logger.info(self.vapi.cli("sh int feat pg0"))
Neale Ranns25b04942018-04-04 09:34:50 -07001051
1052 #
1053 # Packet destined to unknown unicast is sent on the epg uplink ...
1054 #
1055 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1056 dst="00:00:00:33:44:55") /
Neale Rannsc0a93142018-09-05 15:42:26 -07001057 IP(src=eps[0].ip4.address,
1058 dst="10.0.0.99") /
Neale Ranns25b04942018-04-04 09:34:50 -07001059 UDP(sport=1234, dport=1234) /
1060 Raw('\xa5' * 100))
1061
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001062 self.send_and_expect_bridged(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001063 pkt_intra_epg_220_to_uplink * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001064 eps[0].epg.uplink)
Neale Ranns25b04942018-04-04 09:34:50 -07001065 # ... and nowhere else
1066 self.pg1.get_capture(0, timeout=0.1)
1067 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1068
1069 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1070 dst="00:00:00:33:44:66") /
Neale Rannsc0a93142018-09-05 15:42:26 -07001071 IP(src=eps[0].ip4.address,
1072 dst="10.0.0.99") /
Neale Ranns25b04942018-04-04 09:34:50 -07001073 UDP(sport=1234, dport=1234) /
1074 Raw('\xa5' * 100))
1075
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001076 self.send_and_expect_bridged(eps[2].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001077 pkt_intra_epg_221_to_uplink * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001078 eps[2].epg.uplink)
Neale Ranns25b04942018-04-04 09:34:50 -07001079
1080 #
1081 # Packets from the uplink are forwarded in the absence of a contract
1082 #
1083 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1084 dst=self.pg0.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001085 IP(src=eps[0].ip4.address,
1086 dst="10.0.0.99") /
Neale Ranns25b04942018-04-04 09:34:50 -07001087 UDP(sport=1234, dport=1234) /
1088 Raw('\xa5' * 100))
1089
1090 self.send_and_expect_bridged(self.pg4,
1091 pkt_intra_epg_220_from_uplink * 65,
1092 self.pg0)
1093
1094 #
1095 # in the absence of policy, endpoints in the same EPG
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001096 # can communicate
1097 #
1098 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
Neale Ranns25b04942018-04-04 09:34:50 -07001099 dst=self.pg1.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001100 IP(src=eps[0].ip4.address,
1101 dst=eps[1].ip4.address) /
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001102 UDP(sport=1234, dport=1234) /
1103 Raw('\xa5' * 100))
1104
Neale Ranns25b04942018-04-04 09:34:50 -07001105 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001106
1107 #
1108 # in the abscense of policy, endpoints in the different EPG
1109 # cannot communicate
1110 #
1111 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
Neale Ranns25b04942018-04-04 09:34:50 -07001112 dst=self.pg2.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001113 IP(src=eps[0].ip4.address,
1114 dst=eps[2].ip4.address) /
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001115 UDP(sport=1234, dport=1234) /
1116 Raw('\xa5' * 100))
1117 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
Neale Ranns25b04942018-04-04 09:34:50 -07001118 dst=self.pg0.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001119 IP(src=eps[2].ip4.address,
1120 dst=eps[0].ip4.address) /
Neale Ranns25b04942018-04-04 09:34:50 -07001121 UDP(sport=1234, dport=1234) /
1122 Raw('\xa5' * 100))
1123 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -07001124 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001125 IP(src=eps[0].ip4.address,
1126 dst=eps[3].ip4.address) /
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001127 UDP(sport=1234, dport=1234) /
1128 Raw('\xa5' * 100))
1129
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001130 self.send_and_assert_no_replies(eps[0].itf,
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001131 pkt_inter_epg_220_to_221 * 65)
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001132 self.send_and_assert_no_replies(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001133 pkt_inter_epg_220_to_222 * 65)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001134
1135 #
1136 # A uni-directional contract from EPG 220 -> 221
1137 #
Mohsin Kazmi22b3b842018-04-17 19:35:42 +02001138 acl = VppGbpAcl(self)
1139 rule = acl.create_rule(permit_deny=1, proto=17)
1140 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1141 acl_index = acl.add_vpp_config([rule, rule2])
Neale Ranns13a08cc2018-11-07 09:25:54 -08001142 c1 = VppGbpContract(
1143 self, 220, 221, acl_index,
1144 [VppGbpContractRule(
1145 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1146 []),
1147 VppGbpContractRule(
1148 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1149 [])])
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001150 c1.add_vpp_config()
1151
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001152 self.send_and_expect_bridged(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001153 pkt_inter_epg_220_to_221 * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001154 eps[2].itf)
1155 self.send_and_assert_no_replies(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001156 pkt_inter_epg_220_to_222 * 65)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001157
1158 #
1159 # contract for the return direction
1160 #
Neale Ranns13a08cc2018-11-07 09:25:54 -08001161 c2 = VppGbpContract(
1162 self, 221, 220, acl_index,
1163 [VppGbpContractRule(
1164 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1165 []),
1166 VppGbpContractRule(
1167 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1168 [])])
1169
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001170 c2.add_vpp_config()
1171
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001172 self.send_and_expect_bridged(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001173 pkt_inter_epg_220_to_221 * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001174 eps[2].itf)
1175 self.send_and_expect_bridged(eps[2].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001176 pkt_inter_epg_221_to_220 * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001177 eps[0].itf)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001178
1179 #
1180 # check that inter group is still disabled for the groups
1181 # not in the contract.
1182 #
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001183 self.send_and_assert_no_replies(eps[0].itf,
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001184 pkt_inter_epg_220_to_222 * 65)
1185
Neale Ranns25b04942018-04-04 09:34:50 -07001186 #
1187 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1188 #
Neale Ranns13a08cc2018-11-07 09:25:54 -08001189 c3 = VppGbpContract(
1190 self, 220, 222, acl_index,
1191 [VppGbpContractRule(
1192 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1193 []),
1194 VppGbpContractRule(
1195 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1196 [])])
1197
Neale Ranns25b04942018-04-04 09:34:50 -07001198 c3.add_vpp_config()
1199
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001200 self.logger.info(self.vapi.cli("sh gbp contract"))
1201
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001202 self.send_and_expect_routed(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001203 pkt_inter_epg_220_to_222 * 65,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001204 eps[3].itf,
Neale Ranns4d5b9172018-10-24 02:57:49 -07001205 self.router_mac.address)
Neale Ranns25b04942018-04-04 09:34:50 -07001206
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001207 #
1208 # remove both contracts, traffic stops in both directions
1209 #
1210 c2.remove_vpp_config()
1211 c1.remove_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -07001212 c3.remove_vpp_config()
Mohsin Kazmi22b3b842018-04-17 19:35:42 +02001213 acl.remove_vpp_config()
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001214
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001215 self.send_and_assert_no_replies(eps[2].itf,
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001216 pkt_inter_epg_221_to_220 * 65)
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001217 self.send_and_assert_no_replies(eps[0].itf,
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001218 pkt_inter_epg_220_to_221 * 65)
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001219 self.send_and_expect_bridged(eps[0].itf,
1220 pkt_intra_epg * 65,
1221 eps[1].itf)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001222
1223 #
Neale Ranns25b04942018-04-04 09:34:50 -07001224 # EPs to the outside world
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001225 #
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001226
Neale Ranns25b04942018-04-04 09:34:50 -07001227 # in the EP's RD an external subnet via the NAT EPG's recirc
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001228 se1 = VppGbpSubnet(
1229 self, rd0, "0.0.0.0", 0,
1230 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1231 sw_if_index=recirc_nat.recirc.sw_if_index,
1232 epg=epg_nat.epg)
1233 se2 = VppGbpSubnet(
1234 self, rd0, "11.0.0.0", 8,
1235 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1236 sw_if_index=recirc_nat.recirc.sw_if_index,
1237 epg=epg_nat.epg)
1238 se16 = VppGbpSubnet(
1239 self, rd0, "::", 0,
1240 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1241 sw_if_index=recirc_nat.recirc.sw_if_index,
1242 epg=epg_nat.epg)
Neale Ranns25b04942018-04-04 09:34:50 -07001243 # in the NAT RD an external subnet via the NAT EPG's uplink
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001244 se3 = VppGbpSubnet(
1245 self, rd20, "0.0.0.0", 0,
1246 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1247 sw_if_index=epg_nat.uplink.sw_if_index,
1248 epg=epg_nat.epg)
1249 se36 = VppGbpSubnet(
1250 self, rd20, "::", 0,
1251 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1252 sw_if_index=epg_nat.uplink.sw_if_index,
1253 epg=epg_nat.epg)
1254 se4 = VppGbpSubnet(
1255 self, rd20, "11.0.0.0", 8,
1256 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1257 sw_if_index=epg_nat.uplink.sw_if_index,
1258 epg=epg_nat.epg)
1259 se1.add_vpp_config()
1260 se2.add_vpp_config()
1261 se16.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -07001262 se3.add_vpp_config()
Neale Ranns4a6d0232018-04-24 07:45:33 -07001263 se36.add_vpp_config()
Neale Ranns25b04942018-04-04 09:34:50 -07001264 se4.add_vpp_config()
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001265
Neale Ranns25b04942018-04-04 09:34:50 -07001266 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1267 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
Neale Ranns4a6d0232018-04-24 07:45:33 -07001268 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1269 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
Neale Rannsc0a93142018-09-05 15:42:26 -07001270 eps[0].fip6))
Neale Ranns25b04942018-04-04 09:34:50 -07001271
Neale Ranns4a6d0232018-04-24 07:45:33 -07001272 #
1273 # From an EP to an outside addess: IN2OUT
1274 #
Neale Ranns25b04942018-04-04 09:34:50 -07001275 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -07001276 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001277 IP(src=eps[0].ip4.address,
1278 dst="1.1.1.1") /
Neale Ranns25b04942018-04-04 09:34:50 -07001279 UDP(sport=1234, dport=1234) /
1280 Raw('\xa5' * 100))
1281
1282 # no policy yet
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001283 self.send_and_assert_no_replies(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001284 pkt_inter_epg_220_to_global * 65)
1285
Mohsin Kazmi22b3b842018-04-17 19:35:42 +02001286 acl2 = VppGbpAcl(self)
1287 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1288 sport_to=1234, dport_from=1234, dport_to=1234)
1289 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1290 sport_from=1234, sport_to=1234,
1291 dport_from=1234, dport_to=1234)
1292
1293 acl_index2 = acl2.add_vpp_config([rule, rule2])
Neale Ranns13a08cc2018-11-07 09:25:54 -08001294 c4 = VppGbpContract(
1295 self, 220, 333, acl_index2,
1296 [VppGbpContractRule(
1297 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1298 []),
1299 VppGbpContractRule(
1300 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1301 [])])
1302
Neale Ranns25b04942018-04-04 09:34:50 -07001303 c4.add_vpp_config()
1304
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001305 self.send_and_expect_natted(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001306 pkt_inter_epg_220_to_global * 65,
1307 self.pg7,
Neale Rannsc0a93142018-09-05 15:42:26 -07001308 eps[0].fip4.address)
Neale Ranns25b04942018-04-04 09:34:50 -07001309
Neale Ranns4a6d0232018-04-24 07:45:33 -07001310 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -07001311 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001312 IPv6(src=eps[0].ip6.address,
1313 dst="6001::1") /
Neale Ranns4a6d0232018-04-24 07:45:33 -07001314 UDP(sport=1234, dport=1234) /
1315 Raw('\xa5' * 100))
1316
1317 self.send_and_expect_natted6(self.pg0,
1318 pkt_inter_epg_220_to_global * 65,
1319 self.pg7,
Neale Rannsc0a93142018-09-05 15:42:26 -07001320 eps[0].fip6.address)
Neale Ranns4a6d0232018-04-24 07:45:33 -07001321
1322 #
1323 # From a global address to an EP: OUT2IN
1324 #
Neale Ranns4d5b9172018-10-24 02:57:49 -07001325 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
Neale Ranns25b04942018-04-04 09:34:50 -07001326 dst=self.pg0.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001327 IP(dst=eps[0].fip4.address,
Neale Ranns25b04942018-04-04 09:34:50 -07001328 src="1.1.1.1") /
1329 UDP(sport=1234, dport=1234) /
1330 Raw('\xa5' * 100))
1331
1332 self.send_and_assert_no_replies(self.pg7,
1333 pkt_inter_epg_220_from_global * 65)
1334
Neale Ranns13a08cc2018-11-07 09:25:54 -08001335 c5 = VppGbpContract(
1336 self, 333, 220, acl_index2,
1337 [VppGbpContractRule(
1338 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1339 []),
1340 VppGbpContractRule(
1341 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1342 [])])
1343
Neale Ranns25b04942018-04-04 09:34:50 -07001344 c5.add_vpp_config()
1345
1346 self.send_and_expect_unnatted(self.pg7,
1347 pkt_inter_epg_220_from_global * 65,
Neale Ranns4a6d0232018-04-24 07:45:33 -07001348 eps[0].itf,
Neale Rannsc0a93142018-09-05 15:42:26 -07001349 eps[0].ip4.address)
Neale Ranns25b04942018-04-04 09:34:50 -07001350
Neale Ranns4d5b9172018-10-24 02:57:49 -07001351 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
Neale Ranns4a6d0232018-04-24 07:45:33 -07001352 dst=self.pg0.remote_mac) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001353 IPv6(dst=eps[0].fip6.address,
Neale Ranns4a6d0232018-04-24 07:45:33 -07001354 src="6001::1") /
1355 UDP(sport=1234, dport=1234) /
1356 Raw('\xa5' * 100))
1357
1358 self.send_and_expect_unnatted6(self.pg7,
1359 pkt_inter_epg_220_from_global * 65,
Neale Rannsc0a93142018-09-05 15:42:26 -07001360 eps[0].itf,
1361 eps[0].ip6.address)
Neale Ranns4a6d0232018-04-24 07:45:33 -07001362
1363 #
1364 # From a local VM to another local VM using resp. public addresses:
1365 # IN2OUT2IN
1366 #
Neale Ranns25b04942018-04-04 09:34:50 -07001367 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -07001368 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001369 IP(src=eps[0].ip4.address,
1370 dst=eps[1].fip4.address) /
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001371 UDP(sport=1234, dport=1234) /
1372 Raw('\xa5' * 100))
1373
Neale Ranns4a6d0232018-04-24 07:45:33 -07001374 self.send_and_expect_double_natted(eps[0].itf,
Neale Ranns25b04942018-04-04 09:34:50 -07001375 pkt_intra_epg_220_global * 65,
Neale Ranns4a6d0232018-04-24 07:45:33 -07001376 eps[1].itf,
Neale Rannsc0a93142018-09-05 15:42:26 -07001377 eps[0].fip4.address,
1378 eps[1].ip4.address)
Neale Ranns4a6d0232018-04-24 07:45:33 -07001379
Neale Rannsc0a93142018-09-05 15:42:26 -07001380 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
Neale Ranns4d5b9172018-10-24 02:57:49 -07001381 dst=self.router_mac.address) /
Neale Rannsc0a93142018-09-05 15:42:26 -07001382 IPv6(src=eps[0].ip6.address,
1383 dst=eps[1].fip6.address) /
Neale Ranns4a6d0232018-04-24 07:45:33 -07001384 UDP(sport=1234, dport=1234) /
1385 Raw('\xa5' * 100))
1386
Neale Rannsc0a93142018-09-05 15:42:26 -07001387 self.send_and_expect_double_natted6(eps[0].itf,
Neale Ranns4a6d0232018-04-24 07:45:33 -07001388 pkt_intra_epg_220_global * 65,
Neale Rannsc0a93142018-09-05 15:42:26 -07001389 eps[1].itf,
1390 eps[0].fip6.address,
1391 eps[1].ip6.address)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001392
1393 #
Neale Ranns25b04942018-04-04 09:34:50 -07001394 # cleanup
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001395 #
Neale Ranns25b04942018-04-04 09:34:50 -07001396 for ep in eps:
1397 # del static mappings for each EP from the 10/8 to 11/8 network
Neale Rannsc0a93142018-09-05 15:42:26 -07001398 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1399 ep.fip4.bytes,
1400 vrf_id=0,
1401 addr_only=1,
1402 is_add=0)
1403 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1404 ep.fip6.bytes,
1405 vrf_id=0,
1406 is_add=0)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001407
Neale Ranns25b04942018-04-04 09:34:50 -07001408 for epg in epgs:
1409 # IP config on the BVI interfaces
Neale Ranns25b04942018-04-04 09:34:50 -07001410 if epg != epgs[0] and epg != epgs[3]:
Neale Ranns25b04942018-04-04 09:34:50 -07001411 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1412 is_inside=1,
1413 is_add=0)
Neale Ranns4a6d0232018-04-24 07:45:33 -07001414 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1415 is_inside=1,
1416 is_add=0)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001417
Neale Ranns25b04942018-04-04 09:34:50 -07001418 for recirc in recircs:
Neale Ranns4a6d0232018-04-24 07:45:33 -07001419 self.vapi.nat44_interface_add_del_feature(
1420 recirc.recirc.sw_if_index,
1421 is_inside=0,
1422 is_add=0)
1423 self.vapi.nat66_add_del_interface(
1424 recirc.recirc.sw_if_index,
1425 is_inside=0,
1426 is_add=0)
Neale Rannsbc27d1b2018-02-05 01:13:38 -08001427
Neale Ranns774356a2018-11-29 12:02:16 +00001428 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1429 n_tries=100, s_time=1):
1430 while (n_tries):
1431 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1432 return True
1433 n_tries = n_tries - 1
1434 self.sleep(s_time)
1435 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1436 return False
1437
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001438 def test_gbp_learn_l2(self):
1439 """ GBP L2 Endpoint Learning """
1440
Neale Rannsb6a47952018-11-21 05:44:35 -08001441 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001442 learnt = [{'mac': '00:00:11:11:11:01',
1443 'ip': '10.0.0.1',
1444 'ip6': '2001:10::2'},
1445 {'mac': '00:00:11:11:11:02',
1446 'ip': '10.0.0.2',
1447 'ip6': '2001:10::3'}]
1448
1449 #
1450 # lower the inactive threshold so these tests pass in a
1451 # reasonable amount of time
1452 #
1453 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1454
1455 #
1456 # IP tables
1457 #
1458 gt4 = VppIpTable(self, 1)
1459 gt4.add_vpp_config()
1460 gt6 = VppIpTable(self, 1, is_ip6=True)
1461 gt6.add_vpp_config()
1462
1463 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1464 rd1.add_vpp_config()
1465
1466 #
1467 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1468 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1469 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1470 #
1471 self.pg2.config_ip4()
1472 self.pg2.resolve_arp()
1473 self.pg2.generate_remote_hosts(4)
1474 self.pg2.configure_ipv4_neighbors()
1475 self.pg3.config_ip4()
1476 self.pg3.resolve_arp()
1477 self.pg4.config_ip4()
1478 self.pg4.resolve_arp()
1479
1480 #
1481 # a GBP bridge domain with a BVI and a UU-flood interface
1482 #
1483 bd1 = VppBridgeDomain(self, 1)
1484 bd1.add_vpp_config()
1485 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1486 gbd1.add_vpp_config()
1487
1488 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1489 self.logger.info(self.vapi.cli("sh gbp bridge"))
1490
1491 # ... and has a /32 applied
1492 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1493 ip_addr.add_vpp_config()
1494
1495 #
1496 # The Endpoint-group in which we are learning endpoints
1497 #
1498 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1499 None, self.loop0,
1500 "10.0.0.128",
1501 "2001:10::128")
1502 epg_220.add_vpp_config()
1503 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1504 None, self.loop1,
1505 "10.0.1.128",
1506 "2001:11::128")
1507 epg_330.add_vpp_config()
1508
1509 #
1510 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1511 # leanring enabled
1512 #
1513 vx_tun_l2_1 = VppGbpVxlanTunnel(
1514 self, 99, bd1.bd_id,
1515 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1516 vx_tun_l2_1.add_vpp_config()
1517
1518 #
1519 # A static endpoint that the learnt endpoints are trying to
1520 # talk to
1521 #
1522 ep = VppGbpEndpoint(self, self.pg0,
1523 epg_220, None,
1524 "10.0.0.127", "11.0.0.127",
1525 "2001:10::1", "3001::1")
1526 ep.add_vpp_config()
1527
1528 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1529
1530 # a packet with an sclass from an unknwon EPG
1531 p = (Ether(src=self.pg2.remote_mac,
1532 dst=self.pg2.local_mac) /
1533 IP(src=self.pg2.remote_hosts[0].ip4,
1534 dst=self.pg2.local_ip4) /
1535 UDP(sport=1234, dport=48879) /
1536 VXLAN(vni=99, gpid=88, flags=0x88) /
1537 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1538 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1539 UDP(sport=1234, dport=1234) /
1540 Raw('\xa5' * 100))
1541
1542 self.send_and_assert_no_replies(self.pg2, p)
1543
1544 #
1545 # we should not have learnt a new tunnel endpoint, since
1546 # the EPG was not learnt.
1547 #
1548 self.assertEqual(INDEX_INVALID,
1549 find_vxlan_gbp_tunnel(self,
1550 self.pg2.local_ip4,
1551 self.pg2.remote_hosts[0].ip4,
1552 99))
1553
1554 # epg is not learnt, becasue the EPG is unknwon
1555 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1556
1557 for ii, l in enumerate(learnt):
1558 # a packet with an sclass from a knwon EPG
1559 # arriving on an unknown TEP
1560 p = (Ether(src=self.pg2.remote_mac,
1561 dst=self.pg2.local_mac) /
1562 IP(src=self.pg2.remote_hosts[1].ip4,
1563 dst=self.pg2.local_ip4) /
1564 UDP(sport=1234, dport=48879) /
1565 VXLAN(vni=99, gpid=220, flags=0x88) /
1566 Ether(src=l['mac'], dst=ep.mac) /
1567 IP(src=l['ip'], dst=ep.ip4.address) /
1568 UDP(sport=1234, dport=1234) /
1569 Raw('\xa5' * 100))
1570
1571 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1572
1573 # the new TEP
1574 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1575 self,
1576 self.pg2.local_ip4,
1577 self.pg2.remote_hosts[1].ip4,
1578 99)
1579 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1580
1581 #
1582 # the EP is learnt via the learnt TEP
1583 # both from its MAC and its IP
1584 #
1585 self.assertTrue(find_gbp_endpoint(self,
1586 vx_tun_l2_1.sw_if_index,
1587 mac=l['mac']))
1588 self.assertTrue(find_gbp_endpoint(self,
1589 vx_tun_l2_1.sw_if_index,
1590 ip=l['ip']))
1591
1592 self.logger.info(self.vapi.cli("show gbp endpoint"))
1593 self.logger.info(self.vapi.cli("show gbp vxlan"))
1594 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1595
1596 #
1597 # If we sleep for the threshold time, the learnt endpoints should
1598 # age out
1599 #
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001600 for l in learnt:
Neale Ranns774356a2018-11-29 12:02:16 +00001601 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1602 mac=l['mac'])
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001603
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001604 #
1605 # repeat. the do not learn bit is set so the EPs are not learnt
1606 #
1607 for l in learnt:
1608 # a packet with an sclass from a knwon EPG
1609 p = (Ether(src=self.pg2.remote_mac,
1610 dst=self.pg2.local_mac) /
1611 IP(src=self.pg2.remote_hosts[1].ip4,
1612 dst=self.pg2.local_ip4) /
1613 UDP(sport=1234, dport=48879) /
1614 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1615 Ether(src=l['mac'], dst=ep.mac) /
1616 IP(src=l['ip'], dst=ep.ip4.address) /
1617 UDP(sport=1234, dport=1234) /
1618 Raw('\xa5' * 100))
1619
1620 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1621
1622 for l in learnt:
1623 self.assertFalse(find_gbp_endpoint(self,
1624 vx_tun_l2_1.sw_if_index,
1625 mac=l['mac']))
1626
1627 #
1628 # repeat
1629 #
1630 for l in learnt:
1631 # a packet with an sclass from a knwon EPG
1632 p = (Ether(src=self.pg2.remote_mac,
1633 dst=self.pg2.local_mac) /
1634 IP(src=self.pg2.remote_hosts[1].ip4,
1635 dst=self.pg2.local_ip4) /
1636 UDP(sport=1234, dport=48879) /
1637 VXLAN(vni=99, gpid=220, flags=0x88) /
1638 Ether(src=l['mac'], dst=ep.mac) /
1639 IP(src=l['ip'], dst=ep.ip4.address) /
1640 UDP(sport=1234, dport=1234) /
1641 Raw('\xa5' * 100))
1642
1643 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1644
1645 self.assertTrue(find_gbp_endpoint(self,
1646 vx_tun_l2_1.sw_if_index,
1647 mac=l['mac']))
1648
1649 #
1650 # Static EP replies to dynamics
1651 #
1652 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1653 for l in learnt:
1654 p = (Ether(src=ep.mac, dst=l['mac']) /
1655 IP(dst=l['ip'], src=ep.ip4.address) /
1656 UDP(sport=1234, dport=1234) /
1657 Raw('\xa5' * 100))
1658
1659 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1660
1661 for rx in rxs:
1662 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1663 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1664 self.assertEqual(rx[UDP].dport, 48879)
1665 # the UDP source port is a random value for hashing
1666 self.assertEqual(rx[VXLAN].gpid, 220)
1667 self.assertEqual(rx[VXLAN].vni, 99)
1668 self.assertTrue(rx[VXLAN].flags.G)
1669 self.assertTrue(rx[VXLAN].flags.Instance)
1670 self.assertTrue(rx[VXLAN].gpflags.A)
1671 self.assertFalse(rx[VXLAN].gpflags.D)
1672
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001673 for l in learnt:
Neale Ranns774356a2018-11-29 12:02:16 +00001674 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1675 mac=l['mac'])
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001676
1677 #
1678 # repeat in the other EPG
1679 # there's no contract between 220 and 330, but the A-bit is set
1680 # so the packet is cleared for delivery
1681 #
1682 for l in learnt:
1683 # a packet with an sclass from a knwon EPG
1684 p = (Ether(src=self.pg2.remote_mac,
1685 dst=self.pg2.local_mac) /
1686 IP(src=self.pg2.remote_hosts[1].ip4,
1687 dst=self.pg2.local_ip4) /
1688 UDP(sport=1234, dport=48879) /
1689 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1690 Ether(src=l['mac'], dst=ep.mac) /
1691 IP(src=l['ip'], dst=ep.ip4.address) /
1692 UDP(sport=1234, dport=1234) /
1693 Raw('\xa5' * 100))
1694
1695 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1696
1697 self.assertTrue(find_gbp_endpoint(self,
1698 vx_tun_l2_1.sw_if_index,
1699 mac=l['mac']))
1700
1701 #
1702 # static EP cannot reach the learnt EPs since there is no contract
Neale Ranns13a08cc2018-11-07 09:25:54 -08001703 # only test 1 EP as the others could timeout
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001704 #
Neale Ranns13a08cc2018-11-07 09:25:54 -08001705 p = (Ether(src=ep.mac, dst=l['mac']) /
1706 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1707 UDP(sport=1234, dport=1234) /
1708 Raw('\xa5' * 100))
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001709
Neale Ranns13a08cc2018-11-07 09:25:54 -08001710 self.send_and_assert_no_replies(self.pg0, [p])
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001711
1712 #
1713 # refresh the entries after the check for no replies above
1714 #
1715 for l in learnt:
1716 # a packet with an sclass from a knwon EPG
1717 p = (Ether(src=self.pg2.remote_mac,
1718 dst=self.pg2.local_mac) /
1719 IP(src=self.pg2.remote_hosts[1].ip4,
1720 dst=self.pg2.local_ip4) /
1721 UDP(sport=1234, dport=48879) /
1722 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1723 Ether(src=l['mac'], dst=ep.mac) /
1724 IP(src=l['ip'], dst=ep.ip4.address) /
1725 UDP(sport=1234, dport=1234) /
1726 Raw('\xa5' * 100))
1727
1728 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1729
1730 self.assertTrue(find_gbp_endpoint(self,
1731 vx_tun_l2_1.sw_if_index,
1732 mac=l['mac']))
1733
1734 #
1735 # Add the contract so they can talk
1736 #
1737 acl = VppGbpAcl(self)
1738 rule = acl.create_rule(permit_deny=1, proto=17)
1739 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1740 acl_index = acl.add_vpp_config([rule, rule2])
Neale Ranns13a08cc2018-11-07 09:25:54 -08001741 c1 = VppGbpContract(
1742 self, 220, 330, acl_index,
1743 [VppGbpContractRule(
1744 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1745 []),
1746 VppGbpContractRule(
1747 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1748 [])])
1749
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001750 c1.add_vpp_config()
1751
1752 for l in learnt:
1753 p = (Ether(src=ep.mac, dst=l['mac']) /
1754 IP(dst=l['ip'], src=ep.ip4.address) /
1755 UDP(sport=1234, dport=1234) /
1756 Raw('\xa5' * 100))
1757
1758 self.send_and_expect(self.pg0, [p], self.pg2)
1759
1760 #
1761 # send UU packets from the local EP
1762 #
1763 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1764 self.logger.info(self.vapi.cli("sh gbp bridge"))
1765 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1766 IP(dst="10.0.0.133", src=ep.ip4.address) /
1767 UDP(sport=1234, dport=1234) /
1768 Raw('\xa5' * 100))
1769 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1770
1771 #
1772 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1773 #
1774 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1775 "239.1.1.1", 88,
1776 mcast_itf=self.pg4)
1777 tun_bm.add_vpp_config()
1778 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1779 port_type=L2_PORT_TYPE.NORMAL)
1780 bp_bm.add_vpp_config()
1781
1782 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1783
1784 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1785 IP(dst="10.0.0.133", src=ep.ip4.address) /
1786 UDP(sport=1234, dport=1234) /
1787 Raw('\xa5' * 100))
1788 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1789
1790 #
1791 # Check v6 Endpoints
1792 #
1793 for l in learnt:
1794 # a packet with an sclass from a knwon EPG
1795 p = (Ether(src=self.pg2.remote_mac,
1796 dst=self.pg2.local_mac) /
1797 IP(src=self.pg2.remote_hosts[1].ip4,
1798 dst=self.pg2.local_ip4) /
1799 UDP(sport=1234, dport=48879) /
1800 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1801 Ether(src=l['mac'], dst=ep.mac) /
1802 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1803 UDP(sport=1234, dport=1234) /
1804 Raw('\xa5' * 100))
1805
1806 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1807
1808 self.assertTrue(find_gbp_endpoint(self,
1809 vx_tun_l2_1.sw_if_index,
1810 mac=l['mac']))
1811
1812 #
1813 # L3 Endpoint Learning
1814 # - configured on the bridge's BVI
1815 #
1816
1817 #
1818 # clean up
1819 #
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001820 for l in learnt:
Neale Ranns774356a2018-11-29 12:02:16 +00001821 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1822 mac=l['mac'])
Neale Ranns93cc3ee2018-10-10 07:22:51 -07001823
1824 self.pg2.unconfig_ip4()
1825 self.pg3.unconfig_ip4()
1826 self.pg4.unconfig_ip4()
1827
1828 self.logger.info(self.vapi.cli("sh int"))
1829 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1830
juraj.linkes68ebc832018-11-29 09:37:08 +01001831 @unittest.skipIf(is_skip_aarch64_set() and is_platform_aarch64(),
1832 "test doesn't work on aarch64")
Neale Rannsc29c0af2018-11-07 04:21:12 -08001833 def test_gbp_learn_vlan_l2(self):
1834 """ GBP L2 Endpoint w/ VLANs"""
1835
Neale Rannsb6a47952018-11-21 05:44:35 -08001836 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
Neale Rannsc29c0af2018-11-07 04:21:12 -08001837 learnt = [{'mac': '00:00:11:11:11:01',
1838 'ip': '10.0.0.1',
1839 'ip6': '2001:10::2'},
1840 {'mac': '00:00:11:11:11:02',
1841 'ip': '10.0.0.2',
1842 'ip6': '2001:10::3'}]
1843
1844 #
1845 # lower the inactive threshold so these tests pass in a
1846 # reasonable amount of time
1847 #
1848 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1849
1850 #
1851 # IP tables
1852 #
1853 gt4 = VppIpTable(self, 1)
1854 gt4.add_vpp_config()
1855 gt6 = VppIpTable(self, 1, is_ip6=True)
1856 gt6.add_vpp_config()
1857
1858 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1859 rd1.add_vpp_config()
1860
1861 #
1862 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1863 #
1864 self.pg2.config_ip4()
1865 self.pg2.resolve_arp()
1866 self.pg2.generate_remote_hosts(4)
1867 self.pg2.configure_ipv4_neighbors()
1868 self.pg3.config_ip4()
1869 self.pg3.resolve_arp()
1870
1871 #
1872 # The EP will be on a vlan sub-interface
1873 #
1874 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1875 vlan_11.admin_up()
1876 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1877 L2_VTR_OP.L2_POP_1,
1878 11)
1879
1880 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1881 self.pg3.remote_ip4, 116)
1882 bd_uu_fwd.add_vpp_config()
1883
1884 #
1885 # a GBP bridge domain with a BVI and a UU-flood interface
1886 # The BD is marked as do not learn, so no endpoints are ever
1887 # learnt in this BD.
1888 #
1889 bd1 = VppBridgeDomain(self, 1)
1890 bd1.add_vpp_config()
1891 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1892 learn=False)
1893 gbd1.add_vpp_config()
1894
1895 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1896 self.logger.info(self.vapi.cli("sh gbp bridge"))
1897
1898 # ... and has a /32 applied
1899 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1900 ip_addr.add_vpp_config()
1901
1902 #
1903 # The Endpoint-group in which we are learning endpoints
1904 #
1905 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1906 None, self.loop0,
1907 "10.0.0.128",
1908 "2001:10::128")
1909 epg_220.add_vpp_config()
1910
1911 #
1912 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1913 # leanring enabled
1914 #
1915 vx_tun_l2_1 = VppGbpVxlanTunnel(
1916 self, 99, bd1.bd_id,
1917 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1918 vx_tun_l2_1.add_vpp_config()
1919
1920 #
1921 # A static endpoint that the learnt endpoints are trying to
1922 # talk to
1923 #
1924 ep = VppGbpEndpoint(self, vlan_11,
1925 epg_220, None,
1926 "10.0.0.127", "11.0.0.127",
1927 "2001:10::1", "3001::1")
1928 ep.add_vpp_config()
1929
1930 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1931
1932 #
1933 # Send to the static EP
1934 #
1935 for ii, l in enumerate(learnt):
1936 # a packet with an sclass from a knwon EPG
1937 # arriving on an unknown TEP
1938 p = (Ether(src=self.pg2.remote_mac,
1939 dst=self.pg2.local_mac) /
1940 IP(src=self.pg2.remote_hosts[1].ip4,
1941 dst=self.pg2.local_ip4) /
1942 UDP(sport=1234, dport=48879) /
1943 VXLAN(vni=99, gpid=220, flags=0x88) /
1944 Ether(src=l['mac'], dst=ep.mac) /
1945 IP(src=l['ip'], dst=ep.ip4.address) /
1946 UDP(sport=1234, dport=1234) /
1947 Raw('\xa5' * 100))
1948
1949 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1950
1951 #
1952 # packet to EP has the EP's vlan tag
1953 #
1954 for rx in rxs:
1955 self.assertEqual(rx[Dot1Q].vlan, 11)
1956
1957 #
1958 # the EP is not learnt since the BD setting prevents it
1959 # also no TEP too
1960 #
1961 self.assertFalse(find_gbp_endpoint(self,
1962 vx_tun_l2_1.sw_if_index,
1963 mac=l['mac']))
1964 self.assertEqual(INDEX_INVALID,
1965 find_vxlan_gbp_tunnel(
1966 self,
1967 self.pg2.local_ip4,
1968 self.pg2.remote_hosts[1].ip4,
1969 99))
1970
1971 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1972
1973 #
1974 # static to remotes
1975 # we didn't learn the remotes so they are sent to the UU-fwd
1976 #
1977 for l in learnt:
1978 p = (Ether(src=ep.mac, dst=l['mac']) /
1979 Dot1Q(vlan=11) /
1980 IP(dst=l['ip'], src=ep.ip4.address) /
1981 UDP(sport=1234, dport=1234) /
1982 Raw('\xa5' * 100))
1983
1984 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1985
1986 for rx in rxs:
1987 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1988 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1989 self.assertEqual(rx[UDP].dport, 48879)
1990 # the UDP source port is a random value for hashing
1991 self.assertEqual(rx[VXLAN].gpid, 220)
1992 self.assertEqual(rx[VXLAN].vni, 116)
1993 self.assertTrue(rx[VXLAN].flags.G)
1994 self.assertTrue(rx[VXLAN].flags.Instance)
1995 self.assertFalse(rx[VXLAN].gpflags.A)
1996 self.assertFalse(rx[VXLAN].gpflags.D)
1997
1998 self.pg2.unconfig_ip4()
1999 self.pg3.unconfig_ip4()
2000
juraj.linkes68ebc832018-11-29 09:37:08 +01002001 @unittest.skipIf(is_skip_aarch64_set() and is_platform_aarch64(),
2002 "test doesn't work on aarch64")
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002003 def test_gbp_learn_l3(self):
2004 """ GBP L3 Endpoint Learning """
2005
Neale Ranns13a08cc2018-11-07 09:25:54 -08002006 self.vapi.cli("set logging class gbp debug")
2007
Neale Rannsb6a47952018-11-21 05:44:35 -08002008 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002009 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2010 routed_src_mac = "00:22:bd:f8:19:ff"
2011
2012 learnt = [{'mac': '00:00:11:11:11:02',
2013 'ip': '10.0.1.2',
2014 'ip6': '2001:10::2'},
2015 {'mac': '00:00:11:11:11:03',
2016 'ip': '10.0.1.3',
2017 'ip6': '2001:10::3'}]
2018
2019 #
2020 # lower the inactive threshold so these tests pass in a
2021 # reasonable amount of time
2022 #
2023 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2024
2025 #
2026 # IP tables
2027 #
2028 t4 = VppIpTable(self, 1)
2029 t4.add_vpp_config()
2030 t6 = VppIpTable(self, 1, True)
2031 t6.add_vpp_config()
2032
2033 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2034 self.pg4.remote_ip4, 114)
2035 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2036 self.pg4.remote_ip4, 116)
2037 tun_ip4_uu.add_vpp_config()
2038 tun_ip6_uu.add_vpp_config()
2039
2040 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2041 rd1.add_vpp_config()
2042
2043 self.loop0.set_mac(self.router_mac.address)
2044
2045 #
2046 # Bind the BVI to the RD
2047 #
2048 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2049 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2050
2051 #
2052 # Pg2 hosts the vxlan tunnel
2053 # hosts on pg2 to act as TEPs
2054 # pg3 is BD uu-fwd
2055 # pg4 is RD uu-fwd
2056 #
2057 self.pg2.config_ip4()
2058 self.pg2.resolve_arp()
2059 self.pg2.generate_remote_hosts(4)
2060 self.pg2.configure_ipv4_neighbors()
2061 self.pg3.config_ip4()
2062 self.pg3.resolve_arp()
2063 self.pg4.config_ip4()
2064 self.pg4.resolve_arp()
2065
2066 #
2067 # a GBP bridge domain with a BVI and a UU-flood interface
2068 #
2069 bd1 = VppBridgeDomain(self, 1)
2070 bd1.add_vpp_config()
2071 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2072 gbd1.add_vpp_config()
2073
2074 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2075 self.logger.info(self.vapi.cli("sh gbp bridge"))
2076 self.logger.info(self.vapi.cli("sh gbp route"))
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002077
2078 # ... and has a /32 and /128 applied
2079 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2080 ip4_addr.add_vpp_config()
2081 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2082 ip6_addr.add_vpp_config()
2083
2084 #
2085 # The Endpoint-group in which we are learning endpoints
2086 #
2087 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2088 None, self.loop0,
2089 "10.0.0.128",
2090 "2001:10::128")
2091 epg_220.add_vpp_config()
2092
2093 #
2094 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2095 # leanring enabled
2096 #
2097 vx_tun_l3 = VppGbpVxlanTunnel(
2098 self, 101, rd1.rd_id,
2099 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2100 vx_tun_l3.add_vpp_config()
2101
2102 #
2103 # A static endpoint that the learnt endpoints are trying to
2104 # talk to
2105 #
2106 ep = VppGbpEndpoint(self, self.pg0,
2107 epg_220, None,
2108 "10.0.0.127", "11.0.0.127",
2109 "2001:10::1", "3001::1")
2110 ep.add_vpp_config()
2111
2112 #
2113 # learn some remote IPv4 EPs
2114 #
2115 for ii, l in enumerate(learnt):
2116 # a packet with an sclass from a knwon EPG
2117 # arriving on an unknown TEP
2118 p = (Ether(src=self.pg2.remote_mac,
2119 dst=self.pg2.local_mac) /
2120 IP(src=self.pg2.remote_hosts[1].ip4,
2121 dst=self.pg2.local_ip4) /
2122 UDP(sport=1234, dport=48879) /
2123 VXLAN(vni=101, gpid=220, flags=0x88) /
2124 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2125 IP(src=l['ip'], dst=ep.ip4.address) /
2126 UDP(sport=1234, dport=1234) /
2127 Raw('\xa5' * 100))
2128
2129 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2130
2131 # the new TEP
2132 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2133 self,
2134 self.pg2.local_ip4,
2135 self.pg2.remote_hosts[1].ip4,
2136 vx_tun_l3.vni)
2137 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2138
2139 # endpoint learnt via the parent GBP-vxlan interface
2140 self.assertTrue(find_gbp_endpoint(self,
2141 vx_tun_l3._sw_if_index,
2142 ip=l['ip']))
2143
2144 #
2145 # Static IPv4 EP replies to learnt
2146 #
2147 for l in learnt:
2148 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2149 IP(dst=l['ip'], src=ep.ip4.address) /
2150 UDP(sport=1234, dport=1234) /
2151 Raw('\xa5' * 100))
2152
2153 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2154
2155 for rx in rxs:
2156 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2157 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2158 self.assertEqual(rx[UDP].dport, 48879)
2159 # the UDP source port is a random value for hashing
2160 self.assertEqual(rx[VXLAN].gpid, 220)
2161 self.assertEqual(rx[VXLAN].vni, 101)
2162 self.assertTrue(rx[VXLAN].flags.G)
2163 self.assertTrue(rx[VXLAN].flags.Instance)
2164 self.assertTrue(rx[VXLAN].gpflags.A)
2165 self.assertFalse(rx[VXLAN].gpflags.D)
2166
2167 inner = rx[VXLAN].payload
2168
2169 self.assertEqual(inner[Ether].src, routed_src_mac)
2170 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2171 self.assertEqual(inner[IP].src, ep.ip4.address)
2172 self.assertEqual(inner[IP].dst, l['ip'])
2173
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002174 for l in learnt:
2175 self.assertFalse(find_gbp_endpoint(self,
2176 tep1_sw_if_index,
2177 ip=l['ip']))
2178
2179 #
2180 # learn some remote IPv6 EPs
2181 #
2182 for ii, l in enumerate(learnt):
2183 # a packet with an sclass from a knwon EPG
2184 # arriving on an unknown TEP
2185 p = (Ether(src=self.pg2.remote_mac,
2186 dst=self.pg2.local_mac) /
2187 IP(src=self.pg2.remote_hosts[1].ip4,
2188 dst=self.pg2.local_ip4) /
2189 UDP(sport=1234, dport=48879) /
2190 VXLAN(vni=101, gpid=220, flags=0x88) /
2191 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2192 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2193 UDP(sport=1234, dport=1234) /
2194 Raw('\xa5' * 100))
2195
2196 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2197
2198 # the new TEP
2199 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2200 self,
2201 self.pg2.local_ip4,
2202 self.pg2.remote_hosts[1].ip4,
2203 vx_tun_l3.vni)
2204 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2205
2206 self.logger.info(self.vapi.cli("show gbp bridge"))
2207 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2208 self.logger.info(self.vapi.cli("show gbp vxlan"))
2209 self.logger.info(self.vapi.cli("show int addr"))
2210
2211 # endpoint learnt via the TEP
2212 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2213
2214 self.logger.info(self.vapi.cli("show gbp endpoint"))
2215 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2216
2217 #
2218 # Static EP replies to learnt
2219 #
2220 for l in learnt:
2221 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2222 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2223 UDP(sport=1234, dport=1234) /
2224 Raw('\xa5' * 100))
2225
2226 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2227
2228 for rx in rxs:
2229 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2230 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2231 self.assertEqual(rx[UDP].dport, 48879)
2232 # the UDP source port is a random value for hashing
2233 self.assertEqual(rx[VXLAN].gpid, 220)
2234 self.assertEqual(rx[VXLAN].vni, 101)
2235 self.assertTrue(rx[VXLAN].flags.G)
2236 self.assertTrue(rx[VXLAN].flags.Instance)
2237 self.assertTrue(rx[VXLAN].gpflags.A)
2238 self.assertFalse(rx[VXLAN].gpflags.D)
2239
2240 inner = rx[VXLAN].payload
2241
2242 self.assertEqual(inner[Ether].src, routed_src_mac)
2243 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2244 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2245 self.assertEqual(inner[IPv6].dst, l['ip6'])
2246
2247 self.logger.info(self.vapi.cli("sh gbp endpoint"))
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002248 for l in learnt:
Neale Ranns774356a2018-11-29 12:02:16 +00002249 self.wait_for_ep_timeout(ip=l['ip'])
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002250
2251 #
2252 # Static sends to unknown EP with no route
2253 #
2254 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2255 IP(dst="10.0.0.99", src=ep.ip4.address) /
2256 UDP(sport=1234, dport=1234) /
2257 Raw('\xa5' * 100))
2258
2259 self.send_and_assert_no_replies(self.pg0, [p])
2260
2261 #
2262 # Add a route to static EP's v4 and v6 subnet
Neale Rannsb6a47952018-11-21 05:44:35 -08002263 # packets should be sent on the v4/v6 uu=fwd interface resp.
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002264 #
2265 se_10_24 = VppGbpSubnet(
2266 self, rd1, "10.0.0.0", 24,
2267 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2268 se_10_24.add_vpp_config()
2269
2270 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2271 IP(dst="10.0.0.99", src=ep.ip4.address) /
2272 UDP(sport=1234, dport=1234) /
2273 Raw('\xa5' * 100))
2274
2275 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2276 for rx in rxs:
2277 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2278 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2279 self.assertEqual(rx[UDP].dport, 48879)
2280 # the UDP source port is a random value for hashing
2281 self.assertEqual(rx[VXLAN].gpid, 220)
2282 self.assertEqual(rx[VXLAN].vni, 114)
2283 self.assertTrue(rx[VXLAN].flags.G)
2284 self.assertTrue(rx[VXLAN].flags.Instance)
2285 # policy is not applied to packets sent to the uu-fwd interfaces
2286 self.assertFalse(rx[VXLAN].gpflags.A)
2287 self.assertFalse(rx[VXLAN].gpflags.D)
2288
2289 #
2290 # learn some remote IPv4 EPs
2291 #
2292 for ii, l in enumerate(learnt):
2293 # a packet with an sclass from a knwon EPG
2294 # arriving on an unknown TEP
2295 p = (Ether(src=self.pg2.remote_mac,
2296 dst=self.pg2.local_mac) /
2297 IP(src=self.pg2.remote_hosts[1].ip4,
2298 dst=self.pg2.local_ip4) /
2299 UDP(sport=1234, dport=48879) /
2300 VXLAN(vni=101, gpid=220, flags=0x88) /
2301 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2302 IP(src=l['ip'], dst=ep.ip4.address) /
2303 UDP(sport=1234, dport=1234) /
2304 Raw('\xa5' * 100))
2305
2306 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2307
2308 # the new TEP
2309 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2310 self,
2311 self.pg2.local_ip4,
2312 self.pg2.remote_hosts[1].ip4,
2313 vx_tun_l3.vni)
2314 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2315
2316 # endpoint learnt via the parent GBP-vxlan interface
2317 self.assertTrue(find_gbp_endpoint(self,
2318 vx_tun_l3._sw_if_index,
2319 ip=l['ip']))
2320
2321 #
2322 # Add a remote endpoint from the API
2323 #
2324 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2325 epg_220, None,
2326 "10.0.0.88", "11.0.0.88",
2327 "2001:10::88", "3001::88",
Neale Rannsb6a47952018-11-21 05:44:35 -08002328 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002329 self.pg2.local_ip4,
2330 self.pg2.remote_hosts[1].ip4,
2331 mac=None)
2332 rep_88.add_vpp_config()
2333
2334 #
2335 # Add a remote endpoint from the API that matches an existing one
2336 #
2337 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2338 epg_220, None,
2339 learnt[0]['ip'], "11.0.0.101",
2340 learnt[0]['ip6'], "3001::101",
Neale Rannsb6a47952018-11-21 05:44:35 -08002341 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002342 self.pg2.local_ip4,
2343 self.pg2.remote_hosts[1].ip4,
2344 mac=None)
2345 rep_2.add_vpp_config()
2346
2347 #
2348 # Add a route to the leanred EP's v4 subnet
2349 # packets should be send on the v4/v6 uu=fwd interface resp.
2350 #
2351 se_10_1_24 = VppGbpSubnet(
2352 self, rd1, "10.0.1.0", 24,
2353 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2354 se_10_1_24.add_vpp_config()
2355
2356 self.logger.info(self.vapi.cli("show gbp endpoint"))
2357
2358 ips = ["10.0.0.88", learnt[0]['ip']]
2359 for ip in ips:
2360 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2361 IP(dst=ip, src=ep.ip4.address) /
2362 UDP(sport=1234, dport=1234) /
2363 Raw('\xa5' * 100))
2364
2365 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2366
2367 for rx in rxs:
2368 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2369 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2370 self.assertEqual(rx[UDP].dport, 48879)
2371 # the UDP source port is a random value for hashing
2372 self.assertEqual(rx[VXLAN].gpid, 220)
2373 self.assertEqual(rx[VXLAN].vni, 101)
2374 self.assertTrue(rx[VXLAN].flags.G)
2375 self.assertTrue(rx[VXLAN].flags.Instance)
2376 self.assertTrue(rx[VXLAN].gpflags.A)
2377 self.assertFalse(rx[VXLAN].gpflags.D)
2378
2379 inner = rx[VXLAN].payload
2380
2381 self.assertEqual(inner[Ether].src, routed_src_mac)
2382 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2383 self.assertEqual(inner[IP].src, ep.ip4.address)
2384 self.assertEqual(inner[IP].dst, ip)
2385
2386 #
Neale Ranns13a08cc2018-11-07 09:25:54 -08002387 # remove the API remote EPs, only API sourced is gone, the DP
2388 # learnt one remains
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002389 #
2390 rep_88.remove_vpp_config()
2391 rep_2.remove_vpp_config()
2392
2393 self.logger.info(self.vapi.cli("show gbp endpoint"))
2394
Neale Ranns13a08cc2018-11-07 09:25:54 -08002395 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002396
Neale Ranns13a08cc2018-11-07 09:25:54 -08002397 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2398 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2399 UDP(sport=1234, dport=1234) /
2400 Raw('\xa5' * 100))
2401 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002402
Neale Ranns13a08cc2018-11-07 09:25:54 -08002403 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2404
2405 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2406 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2407 UDP(sport=1234, dport=1234) /
2408 Raw('\xa5' * 100))
2409 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2410
2411 #
2412 # to appease the testcase we cannot have the registered EP stll
2413 # present (because it's DP learnt) when the TC ends so wait until
2414 # it is removed
2415 #
2416 self.sleep(2)
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002417
2418 #
2419 # shutdown with learnt endpoint present
2420 #
Neale Ranns13a08cc2018-11-07 09:25:54 -08002421 p = (Ether(src=self.pg2.remote_mac,
2422 dst=self.pg2.local_mac) /
2423 IP(src=self.pg2.remote_hosts[1].ip4,
2424 dst=self.pg2.local_ip4) /
2425 UDP(sport=1234, dport=48879) /
2426 VXLAN(vni=101, gpid=220, flags=0x88) /
2427 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2428 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2429 UDP(sport=1234, dport=1234) /
2430 Raw('\xa5' * 100))
2431
2432 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2433
2434 # endpoint learnt via the parent GBP-vxlan interface
2435 self.assertTrue(find_gbp_endpoint(self,
2436 vx_tun_l3._sw_if_index,
2437 ip=l['ip']))
Neale Ranns93cc3ee2018-10-10 07:22:51 -07002438
2439 #
2440 # TODO
2441 # remote endpoint becomes local
2442 #
2443 self.pg2.unconfig_ip4()
2444 self.pg3.unconfig_ip4()
2445 self.pg4.unconfig_ip4()
2446
Neale Ranns13a08cc2018-11-07 09:25:54 -08002447 def test_gbp_redirect(self):
2448 """ GBP Endpoint Redirect """
2449
2450 self.vapi.cli("set logging class gbp debug")
2451
Neale Rannsb6a47952018-11-21 05:44:35 -08002452 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
Neale Ranns13a08cc2018-11-07 09:25:54 -08002453 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2454 routed_src_mac = "00:22:bd:f8:19:ff"
2455
2456 learnt = [{'mac': '00:00:11:11:11:02',
2457 'ip': '10.0.1.2',
2458 'ip6': '2001:10::2'},
2459 {'mac': '00:00:11:11:11:03',
2460 'ip': '10.0.1.3',
2461 'ip6': '2001:10::3'}]
2462
2463 #
2464 # lower the inactive threshold so these tests pass in a
2465 # reasonable amount of time
2466 #
2467 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2468
2469 #
2470 # IP tables
2471 #
2472 t4 = VppIpTable(self, 1)
2473 t4.add_vpp_config()
2474 t6 = VppIpTable(self, 1, True)
2475 t6.add_vpp_config()
2476
2477 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2478 rd1.add_vpp_config()
2479
2480 self.loop0.set_mac(self.router_mac.address)
2481
2482 #
2483 # Bind the BVI to the RD
2484 #
2485 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2486 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2487
2488 #
2489 # Pg7 hosts a BD's UU-fwd
2490 #
2491 self.pg7.config_ip4()
2492 self.pg7.resolve_arp()
2493
2494 #
2495 # a GBP bridge domains for the EPs
2496 #
2497 bd1 = VppBridgeDomain(self, 1)
2498 bd1.add_vpp_config()
2499 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2500 gbd1.add_vpp_config()
2501
2502 bd2 = VppBridgeDomain(self, 2)
2503 bd2.add_vpp_config()
2504 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2505 gbd2.add_vpp_config()
2506
2507 # ... and has a /32 and /128 applied
2508 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2509 ip4_addr.add_vpp_config()
2510 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2511 ip6_addr.add_vpp_config()
2512 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2513 ip4_addr.add_vpp_config()
2514 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2515 ip6_addr.add_vpp_config()
2516
2517 #
2518 # The Endpoint-groups in which we are learning endpoints
2519 #
2520 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2521 None, gbd1.bvi,
2522 "10.0.0.128",
2523 "2001:10::128")
2524 epg_220.add_vpp_config()
2525 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2526 None, gbd2.bvi,
2527 "10.0.1.128",
2528 "2001:11::128")
2529 epg_221.add_vpp_config()
2530 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2531 None, gbd1.bvi,
2532 "10.0.2.128",
2533 "2001:12::128")
2534 epg_222.add_vpp_config()
2535
2536 #
2537 # a GBP bridge domains for the SEPs
2538 #
2539 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2540 self.pg7.remote_ip4, 116)
2541 bd_uu1.add_vpp_config()
2542 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2543 self.pg7.remote_ip4, 117)
2544 bd_uu2.add_vpp_config()
2545
2546 bd3 = VppBridgeDomain(self, 3)
2547 bd3.add_vpp_config()
2548 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2549 gbd3.add_vpp_config()
2550 bd4 = VppBridgeDomain(self, 4)
2551 bd4.add_vpp_config()
2552 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2553 gbd4.add_vpp_config()
2554
2555 #
2556 # EPGs in which the service endpoints exist
2557 #
2558 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2559 None, gbd1.bvi,
2560 "12.0.0.128",
2561 "4001:10::128")
2562 epg_320.add_vpp_config()
2563 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2564 None, gbd2.bvi,
2565 "12.0.1.128",
2566 "4001:11::128")
2567 epg_321.add_vpp_config()
2568
2569 #
2570 # three local endpoints
2571 #
2572 ep1 = VppGbpEndpoint(self, self.pg0,
2573 epg_220, None,
2574 "10.0.0.1", "11.0.0.1",
2575 "2001:10::1", "3001:10::1")
2576 ep1.add_vpp_config()
2577 ep2 = VppGbpEndpoint(self, self.pg1,
2578 epg_221, None,
2579 "10.0.1.1", "11.0.1.1",
2580 "2001:11::1", "3001:11::1")
2581 ep2.add_vpp_config()
2582 ep3 = VppGbpEndpoint(self, self.pg2,
2583 epg_222, None,
2584 "10.0.2.2", "11.0.2.2",
2585 "2001:12::1", "3001:12::1")
2586 ep3.add_vpp_config()
2587
2588 #
2589 # service endpoints
2590 #
2591 sep1 = VppGbpEndpoint(self, self.pg3,
2592 epg_320, None,
2593 "12.0.0.1", "13.0.0.1",
2594 "4001:10::1", "5001:10::1")
2595 sep1.add_vpp_config()
2596 sep2 = VppGbpEndpoint(self, self.pg4,
2597 epg_320, None,
2598 "12.0.0.2", "13.0.0.2",
2599 "4001:10::2", "5001:10::2")
2600 sep2.add_vpp_config()
2601 sep3 = VppGbpEndpoint(self, self.pg5,
2602 epg_321, None,
2603 "12.0.1.1", "13.0.1.1",
2604 "4001:11::1", "5001:11::1")
2605 sep3.add_vpp_config()
2606 # this EP is not installed immediately
2607 sep4 = VppGbpEndpoint(self, self.pg6,
2608 epg_321, None,
2609 "12.0.1.2", "13.0.1.2",
2610 "4001:11::2", "5001:11::2")
2611
2612 #
2613 # an L2 switch packet between local EPs in different EPGs
2614 # different dest ports on each so the are LB hashed differently
2615 #
2616 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2617 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2618 UDP(sport=1234, dport=1234) /
2619 Raw('\xa5' * 100)),
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002620 (Ether(src=ep3.mac, dst=ep1.mac) /
2621 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2622 UDP(sport=1234, dport=1234) /
Neale Ranns13a08cc2018-11-07 09:25:54 -08002623 Raw('\xa5' * 100))]
2624 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2625 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2626 UDP(sport=1234, dport=1234) /
2627 Raw('\xa5' * 100)),
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002628 (Ether(src=ep3.mac, dst=ep1.mac) /
2629 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
Neale Ranns13a08cc2018-11-07 09:25:54 -08002630 UDP(sport=1234, dport=1230) /
2631 Raw('\xa5' * 100))]
2632
2633 # should be dropped since no contract yet
2634 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2635 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2636
2637 #
2638 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2639 # one of the next-hops is via an EP that is not known
2640 #
2641 acl = VppGbpAcl(self)
2642 rule4 = acl.create_rule(permit_deny=1, proto=17)
2643 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2644 acl_index = acl.add_vpp_config([rule4, rule6])
2645
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002646 #
2647 # test the src-ip hash mode
2648 #
Neale Ranns13a08cc2018-11-07 09:25:54 -08002649 c1 = VppGbpContract(
2650 self, 220, 222, acl_index,
2651 [VppGbpContractRule(
2652 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002653 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
Neale Ranns13a08cc2018-11-07 09:25:54 -08002654 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2655 sep1.ip4, sep1.epg.rd),
2656 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2657 sep2.ip4, sep2.epg.rd)]),
2658 VppGbpContractRule(
2659 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002660 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
Neale Ranns13a08cc2018-11-07 09:25:54 -08002661 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2662 sep3.ip6, sep3.epg.rd),
2663 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2664 sep4.ip6, sep4.epg.rd)])])
2665 c1.add_vpp_config()
2666
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002667 c2 = VppGbpContract(
2668 self, 222, 220, acl_index,
2669 [VppGbpContractRule(
2670 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2671 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2672 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2673 sep1.ip4, sep1.epg.rd),
2674 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2675 sep2.ip4, sep2.epg.rd)]),
2676 VppGbpContractRule(
2677 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2678 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2679 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2680 sep3.ip6, sep3.epg.rd),
2681 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2682 sep4.ip6, sep4.epg.rd)])])
2683 c2.add_vpp_config()
2684
Neale Ranns13a08cc2018-11-07 09:25:54 -08002685 #
2686 # send again with the contract preset, now packets arrive
2687 # at SEP1 or SEP2 depending on the hashing
2688 #
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002689 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
Neale Ranns13a08cc2018-11-07 09:25:54 -08002690
2691 for rx in rxs:
2692 self.assertEqual(rx[Ether].src, routed_src_mac)
2693 self.assertEqual(rx[Ether].dst, sep1.mac)
2694 self.assertEqual(rx[IP].src, ep1.ip4.address)
2695 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2696
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002697 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2698
2699 for rx in rxs:
2700 self.assertEqual(rx[Ether].src, routed_src_mac)
2701 self.assertEqual(rx[Ether].dst, sep2.mac)
2702 self.assertEqual(rx[IP].src, ep3.ip4.address)
2703 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2704
Neale Ranns13a08cc2018-11-07 09:25:54 -08002705 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2706
2707 for rx in rxs:
2708 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2709 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2710 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2711 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2712 self.assertEqual(rx[VXLAN].vni, 117)
2713 self.assertTrue(rx[VXLAN].flags.G)
2714 self.assertTrue(rx[VXLAN].flags.Instance)
2715 # redirect policy has been applied
2716 self.assertTrue(rx[VXLAN].gpflags.A)
2717 self.assertFalse(rx[VXLAN].gpflags.D)
2718
2719 inner = rx[VXLAN].payload
2720
2721 self.assertEqual(inner[Ether].src, routed_src_mac)
2722 self.assertEqual(inner[Ether].dst, sep4.mac)
2723 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2724 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2725
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002726 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
Neale Ranns13a08cc2018-11-07 09:25:54 -08002727
2728 for rx in rxs:
2729 self.assertEqual(rx[Ether].src, routed_src_mac)
2730 self.assertEqual(rx[Ether].dst, sep3.mac)
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002731 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2732 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
Neale Ranns13a08cc2018-11-07 09:25:54 -08002733
2734 #
2735 # programme the unknown EP
2736 #
2737 sep4.add_vpp_config()
2738
2739 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2740
2741 for rx in rxs:
2742 self.assertEqual(rx[Ether].src, routed_src_mac)
2743 self.assertEqual(rx[Ether].dst, sep4.mac)
2744 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2745 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2746
2747 #
2748 # and revert back to unprogrammed
2749 #
2750 sep4.remove_vpp_config()
2751
2752 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2753
2754 for rx in rxs:
2755 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2756 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2757 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2758 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2759 self.assertEqual(rx[VXLAN].vni, 117)
2760 self.assertTrue(rx[VXLAN].flags.G)
2761 self.assertTrue(rx[VXLAN].flags.Instance)
2762 # redirect policy has been applied
2763 self.assertTrue(rx[VXLAN].gpflags.A)
2764 self.assertFalse(rx[VXLAN].gpflags.D)
2765
2766 inner = rx[VXLAN].payload
2767
2768 self.assertEqual(inner[Ether].src, routed_src_mac)
2769 self.assertEqual(inner[Ether].dst, sep4.mac)
2770 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2771 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2772
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002773 c1.remove_vpp_config()
2774 c2.remove_vpp_config()
2775
2776 #
2777 # test the symmetric hash mode
2778 #
2779 c1 = VppGbpContract(
2780 self, 220, 222, acl_index,
2781 [VppGbpContractRule(
2782 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2783 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2784 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2785 sep1.ip4, sep1.epg.rd),
2786 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2787 sep2.ip4, sep2.epg.rd)]),
2788 VppGbpContractRule(
2789 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2790 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2791 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2792 sep3.ip6, sep3.epg.rd),
2793 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2794 sep4.ip6, sep4.epg.rd)])])
2795 c1.add_vpp_config()
2796
2797 c2 = VppGbpContract(
2798 self, 222, 220, acl_index,
2799 [VppGbpContractRule(
2800 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2801 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2802 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2803 sep1.ip4, sep1.epg.rd),
2804 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2805 sep2.ip4, sep2.epg.rd)]),
2806 VppGbpContractRule(
2807 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2808 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2809 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2810 sep3.ip6, sep3.epg.rd),
2811 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2812 sep4.ip6, sep4.epg.rd)])])
2813 c2.add_vpp_config()
2814
2815 #
2816 # send again with the contract preset, now packets arrive
2817 # at SEP1 for both directions
2818 #
2819 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2820
2821 for rx in rxs:
2822 self.assertEqual(rx[Ether].src, routed_src_mac)
2823 self.assertEqual(rx[Ether].dst, sep1.mac)
2824 self.assertEqual(rx[IP].src, ep1.ip4.address)
2825 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2826
2827 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2828
2829 for rx in rxs:
2830 self.assertEqual(rx[Ether].src, routed_src_mac)
2831 self.assertEqual(rx[Ether].dst, sep1.mac)
2832 self.assertEqual(rx[IP].src, ep3.ip4.address)
2833 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2834
Neale Ranns13a08cc2018-11-07 09:25:54 -08002835 #
2836 # programme the unknown EP for the L3 tests
2837 #
2838 sep4.add_vpp_config()
2839
2840 #
2841 # an L3 switch packet between local EPs in different EPGs
2842 # different dest ports on each so the are LB hashed differently
2843 #
2844 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2845 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2846 UDP(sport=1234, dport=1234) /
2847 Raw('\xa5' * 100)),
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002848 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2849 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2850 UDP(sport=1234, dport=1234) /
Neale Ranns13a08cc2018-11-07 09:25:54 -08002851 Raw('\xa5' * 100))]
2852 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2853 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2854 UDP(sport=1234, dport=1234) /
2855 Raw('\xa5' * 100)),
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002856 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2857 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2858 UDP(sport=1234, dport=1234) /
Neale Ranns13a08cc2018-11-07 09:25:54 -08002859 Raw('\xa5' * 100))]
2860
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002861 c3 = VppGbpContract(
2862 self, 220, 221, acl_index,
2863 [VppGbpContractRule(
Neale Ranns13a08cc2018-11-07 09:25:54 -08002864 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002865 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2866 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2867 sep1.ip4, sep1.epg.rd),
2868 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2869 sep2.ip4, sep2.epg.rd)]),
2870 VppGbpContractRule(
2871 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2872 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2873 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2874 sep3.ip6, sep3.epg.rd),
2875 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2876 sep4.ip6, sep4.epg.rd)])])
2877 c3.add_vpp_config()
Neale Ranns13a08cc2018-11-07 09:25:54 -08002878
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002879 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
Neale Ranns13a08cc2018-11-07 09:25:54 -08002880
2881 for rx in rxs:
2882 self.assertEqual(rx[Ether].src, routed_src_mac)
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002883 self.assertEqual(rx[Ether].dst, sep1.mac)
Neale Ranns13a08cc2018-11-07 09:25:54 -08002884 self.assertEqual(rx[IP].src, ep1.ip4.address)
2885 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2886
2887 #
2888 # learn a remote EP in EPG 221
2889 #
2890 vx_tun_l3 = VppGbpVxlanTunnel(
2891 self, 444, rd1.rd_id,
2892 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2893 vx_tun_l3.add_vpp_config()
2894
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002895 c4 = VppGbpContract(
Neale Ranns13a08cc2018-11-07 09:25:54 -08002896 self, 221, 220, acl_index,
2897 [VppGbpContractRule(
2898 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2899 []),
2900 VppGbpContractRule(
2901 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2902 [])])
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002903 c4.add_vpp_config()
Neale Ranns13a08cc2018-11-07 09:25:54 -08002904
2905 p = (Ether(src=self.pg7.remote_mac,
2906 dst=self.pg7.local_mac) /
2907 IP(src=self.pg7.remote_ip4,
2908 dst=self.pg7.local_ip4) /
2909 UDP(sport=1234, dport=48879) /
2910 VXLAN(vni=444, gpid=221, flags=0x88) /
2911 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2912 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2913 UDP(sport=1234, dport=1234) /
2914 Raw('\xa5' * 100))
2915
2916 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2917
2918 # endpoint learnt via the parent GBP-vxlan interface
2919 self.assertTrue(find_gbp_endpoint(self,
2920 vx_tun_l3._sw_if_index,
2921 ip="10.0.0.88"))
2922
2923 p = (Ether(src=self.pg7.remote_mac,
2924 dst=self.pg7.local_mac) /
2925 IP(src=self.pg7.remote_ip4,
2926 dst=self.pg7.local_ip4) /
2927 UDP(sport=1234, dport=48879) /
2928 VXLAN(vni=444, gpid=221, flags=0x88) /
2929 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2930 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2931 UDP(sport=1234, dport=1234) /
2932 Raw('\xa5' * 100))
2933
2934 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2935
2936 # endpoint learnt via the parent GBP-vxlan interface
2937 self.assertTrue(find_gbp_endpoint(self,
2938 vx_tun_l3._sw_if_index,
2939 ip="2001:10::88"))
2940
2941 #
2942 # L3 switch from local to remote EP
2943 #
2944 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2945 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2946 UDP(sport=1234, dport=1234) /
Neale Ranns13a08cc2018-11-07 09:25:54 -08002947 Raw('\xa5' * 100))]
2948 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2949 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2950 UDP(sport=1234, dport=1234) /
Neale Ranns13a08cc2018-11-07 09:25:54 -08002951 Raw('\xa5' * 100))]
2952
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002953 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
Neale Ranns13a08cc2018-11-07 09:25:54 -08002954
2955 for rx in rxs:
2956 self.assertEqual(rx[Ether].src, routed_src_mac)
2957 self.assertEqual(rx[Ether].dst, sep1.mac)
2958 self.assertEqual(rx[IP].src, ep1.ip4.address)
2959 self.assertEqual(rx[IP].dst, "10.0.0.88")
2960
2961 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2962
2963 for rx in rxs:
2964 self.assertEqual(rx[Ether].src, routed_src_mac)
2965 self.assertEqual(rx[Ether].dst, sep4.mac)
2966 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2967 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2968
Mohsin Kazmid40c3e62018-11-21 10:46:57 +01002969 #
2970 # test the dst-ip hash mode
2971 #
2972 c5 = VppGbpContract(
2973 self, 220, 221, acl_index,
2974 [VppGbpContractRule(
2975 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2976 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2977 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2978 sep1.ip4, sep1.epg.rd),
2979 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2980 sep2.ip4, sep2.epg.rd)]),
2981 VppGbpContractRule(
2982 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2983 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2984 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2985 sep3.ip6, sep3.epg.rd),
2986 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2987 sep4.ip6, sep4.epg.rd)])])
2988 c5.add_vpp_config()
2989
2990 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2991
2992 for rx in rxs:
2993 self.assertEqual(rx[Ether].src, routed_src_mac)
2994 self.assertEqual(rx[Ether].dst, sep1.mac)
2995 self.assertEqual(rx[IP].src, ep1.ip4.address)
2996 self.assertEqual(rx[IP].dst, "10.0.0.88")
2997
2998 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
Neale Ranns13a08cc2018-11-07 09:25:54 -08002999
3000 for rx in rxs:
3001 self.assertEqual(rx[Ether].src, routed_src_mac)
3002 self.assertEqual(rx[Ether].dst, sep3.mac)
3003 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3004 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3005
Neale Rannsb6a47952018-11-21 05:44:35 -08003006 #
3007 # cleanup
3008 #
3009 self.pg7.unconfig_ip4()
3010
3011 def test_gbp_l3_out(self):
3012 """ GBP L3 Out """
3013
3014 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3015 self.vapi.cli("set logging class gbp debug")
3016
3017 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3018 routed_src_mac = "00:22:bd:f8:19:ff"
3019
3020 #
3021 # IP tables
3022 #
3023 t4 = VppIpTable(self, 1)
3024 t4.add_vpp_config()
3025 t6 = VppIpTable(self, 1, True)
3026 t6.add_vpp_config()
3027
3028 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3029 rd1.add_vpp_config()
3030
3031 self.loop0.set_mac(self.router_mac.address)
3032
3033 #
3034 # Bind the BVI to the RD
3035 #
3036 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3037 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3038
3039 #
3040 # Pg7 hosts a BD's BUM
3041 # Pg1 some other l3 interface
3042 #
3043 self.pg7.config_ip4()
3044 self.pg7.resolve_arp()
3045
3046 #
3047 # a GBP external bridge domains for the EPs
3048 #
3049 bd1 = VppBridgeDomain(self, 1)
3050 bd1.add_vpp_config()
3051 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
3052 gbd1.add_vpp_config()
3053
3054 #
3055 # The Endpoint-groups in which the external endpoints exist
3056 #
3057 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
3058 None, gbd1.bvi,
3059 "10.0.0.128",
3060 "2001:10::128")
3061 epg_220.add_vpp_config()
3062
3063 # the BVIs have the subnets applied ...
3064 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3065 ip4_addr.add_vpp_config()
3066 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3067 ip6_addr.add_vpp_config()
3068
3069 # ... which are L3-out subnets
3070 l3o_1 = VppGbpSubnet(
3071 self, rd1, "10.0.0.0", 24,
3072 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3073 epg=200)
3074 l3o_1.add_vpp_config()
3075
3076 #
3077 # an external interface attached to the outside world and the
3078 # external BD
3079 #
3080 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3081 vlan_100.admin_up()
3082 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3083 ext_itf.add_vpp_config()
3084
3085 #
3086 # a multicast vxlan-gbp tunnel for broadcast in the BD
3087 #
3088 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3089 "239.1.1.1", 88,
3090 mcast_itf=self.pg7)
3091 tun_bm.add_vpp_config()
3092 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
3093 port_type=L2_PORT_TYPE.NORMAL)
3094 bp_bm.add_vpp_config()
3095
3096 #
3097 # an unicast vxlan-gbp for inter-BD traffic
3098 #
3099 vx_tun_l3 = VppGbpVxlanTunnel(
3100 self, 444, rd1.rd_id,
3101 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3102 vx_tun_l3.add_vpp_config()
3103
3104 #
3105 # packets destined to unkown addresses in the BVI's subnet
3106 # are ARP'd for
3107 #
3108 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3109 Dot1Q(vlan=100) /
3110 IP(src="10.0.0.1", dst="10.0.0.88") /
3111 UDP(sport=1234, dport=1234) /
3112 Raw('\xa5' * 100))
3113 p6 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3114 Dot1Q(vlan=100) /
3115 IPv6(src="2001:10::1", dst="2001:10::88") /
3116 UDP(sport=1234, dport=1234) /
3117 Raw('\xa5' * 100))
3118
3119 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3120
3121 for rx in rxs:
3122 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3123 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3124 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3125 self.assertEqual(rx[IP].dst, "239.1.1.1")
3126 self.assertEqual(rx[VXLAN].vni, 88)
3127 self.assertTrue(rx[VXLAN].flags.G)
3128 self.assertTrue(rx[VXLAN].flags.Instance)
3129 # policy is not applied since we don't know where it's going
3130 self.assertFalse(rx[VXLAN].gpflags.A)
3131 self.assertFalse(rx[VXLAN].gpflags.D)
3132
3133 inner = rx[VXLAN].payload
3134
3135 self.assertTrue(inner.haslayer(ARP))
3136
3137 #
3138 # An external Endpoint
3139 #
3140 eep = VppGbpEndpoint(self, vlan_100,
3141 epg_220, None,
3142 "10.0.0.1", "11.0.0.1",
3143 "2001:10::1", "3001::1",
3144 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3145 eep.add_vpp_config()
3146
3147 #
3148 # A remote endpoint
3149 #
3150 rep = VppGbpEndpoint(self, vx_tun_l3,
3151 epg_220, None,
3152 "10.0.0.101", "11.0.0.101",
3153 "2001:10::101", "3001::101",
3154 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3155 self.pg7.local_ip4,
3156 self.pg7.remote_ip4,
3157 mac=None)
3158 rep.add_vpp_config()
3159
3160 #
3161 # remote to external
3162 #
3163 p = (Ether(src=self.pg7.remote_mac,
3164 dst=self.pg7.local_mac) /
3165 IP(src=self.pg7.remote_ip4,
3166 dst=self.pg7.local_ip4) /
3167 UDP(sport=1234, dport=48879) /
3168 VXLAN(vni=444, gpid=220, flags=0x88) /
3169 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3170 IP(src="10.0.0.101", dst="10.0.0.1") /
3171 UDP(sport=1234, dport=1234) /
3172 Raw('\xa5' * 100))
3173
3174 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3175
3176 #
3177 # A subnet reachable through the external EP
3178 #
3179 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3180 [VppRoutePath(eep.ip4.address,
3181 eep.epg.bvi.sw_if_index)],
3182 table_id=t4.table_id)
3183 ip_220.add_vpp_config()
3184
3185 l3o_220 = VppGbpSubnet(
3186 self, rd1, "10.220.0.0", 24,
3187 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3188 epg=220)
3189 l3o_220.add_vpp_config()
3190
3191 p = (Ether(src=self.pg7.remote_mac,
3192 dst=self.pg7.local_mac) /
3193 IP(src=self.pg7.remote_ip4,
3194 dst=self.pg7.local_ip4) /
3195 UDP(sport=1234, dport=48879) /
3196 VXLAN(vni=444, gpid=220, flags=0x88) /
3197 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3198 IP(src="10.0.0.101", dst="10.220.0.1") /
3199 UDP(sport=1234, dport=1234) /
3200 Raw('\xa5' * 100))
3201
3202 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3203
3204 #
3205 # another external subnet, this time in a different EPG
3206 #
3207 ip_200 = VppIpRoute(self, "10.200.0.0", 24,
3208 [VppRoutePath(eep.ip4.address,
3209 eep.epg.bvi.sw_if_index)],
3210 table_id=t4.table_id)
3211 ip_200.add_vpp_config()
3212
3213 l3o_200 = VppGbpSubnet(
3214 self, rd1, "10.200.0.0", 24,
3215 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3216 epg=200)
3217 l3o_200.add_vpp_config()
3218
3219 p = (Ether(src=self.pg7.remote_mac,
3220 dst=self.pg7.local_mac) /
3221 IP(src=self.pg7.remote_ip4,
3222 dst=self.pg7.local_ip4) /
3223 UDP(sport=1234, dport=48879) /
3224 VXLAN(vni=444, gpid=220, flags=0x88) /
3225 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3226 IP(src="10.0.0.101", dst="10.200.0.1") /
3227 UDP(sport=1234, dport=1234) /
3228 Raw('\xa5' * 100))
3229
3230 #
3231 # packets dropped due to lack of contract.
3232 #
3233 rxs = self.send_and_assert_no_replies(self.pg7, p * 1)
3234
3235 #
3236 # from the the subnet in EPG 220 beyond the external to remote
3237 #
3238 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3239 Dot1Q(vlan=100) /
3240 IP(src="10.220.0.1", dst=rep.ip4.address) /
3241 UDP(sport=1234, dport=1234) /
3242 Raw('\xa5' * 100))
3243
3244 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3245
3246 for rx in rxs:
3247 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3248 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3249 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3250 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3251 self.assertEqual(rx[VXLAN].vni, 444)
3252 self.assertTrue(rx[VXLAN].flags.G)
3253 self.assertTrue(rx[VXLAN].flags.Instance)
3254 self.assertTrue(rx[VXLAN].gpflags.A)
3255 self.assertFalse(rx[VXLAN].gpflags.D)
3256
3257 #
3258 # from the the subnet in EPG 200 beyond the external to remote
3259 # dropped due to no contract
3260 #
3261 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3262 Dot1Q(vlan=100) /
3263 IP(src="10.200.0.1", dst=rep.ip4.address) /
3264 UDP(sport=1234, dport=1234) /
3265 Raw('\xa5' * 100))
3266
3267 rxs = self.send_and_assert_no_replies(self.pg0, p4 * 1)
3268
3269 #
3270 # add a contract
3271 #
3272 acl = VppGbpAcl(self)
3273 rule = acl.create_rule(permit_deny=1, proto=17)
3274 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3275 acl_index = acl.add_vpp_config([rule, rule2])
3276 c1 = VppGbpContract(
3277 self, 200, 220, acl_index,
3278 [VppGbpContractRule(
3279 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3280 []),
3281 VppGbpContractRule(
3282 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3283 [])])
3284 c1.add_vpp_config()
3285
3286 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3287
3288 for rx in rxs:
3289 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3290 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3291 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3292 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3293 self.assertEqual(rx[VXLAN].vni, 444)
3294 self.assertTrue(rx[VXLAN].flags.G)
3295 self.assertTrue(rx[VXLAN].flags.Instance)
3296 self.assertTrue(rx[VXLAN].gpflags.A)
3297 self.assertFalse(rx[VXLAN].gpflags.D)
3298
3299 #
3300 # cleanup
3301 #
3302 self.pg7.unconfig_ip4()
3303
Neale Rannsbc27d1b2018-02-05 01:13:38 -08003304
3305if __name__ == '__main__':
3306 unittest.main(testRunner=VppTestRunner)