blob: f2529e8f6f2565787f0cbb889e03cdbfa41b46b6 [file] [log] [blame]
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +01001#!/usr/bin/env python
2
3import unittest
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +01004
5from scapy.packet import Raw
Eyal Bari001fd402017-07-16 09:34:53 +03006from scapy.layers.l2 import Ether, Dot1Q, GRE
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +01007from scapy.layers.inet import IP, UDP
Eyal Bari001fd402017-07-16 09:34:53 +03008from scapy.layers.vxlan import VXLAN
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +01009
10from framework import VppTestCase, VppTestRunner
Klement Sekera7bb873a2016-11-18 07:38:42 +010011from util import Host, ppp
Eyal Bari001fd402017-07-16 09:34:53 +030012from vpp_sub_interface import VppDot1QSubint, VppDot1ADSubint
13from vpp_gre_interface import VppGreInterface, VppGre6Interface
14from vpp_papi_provider import L2_VTR_OP
15from collections import namedtuple
16
17Tag = namedtuple('Tag', ['dot1', 'vlan'])
18DOT1AD = 0x88A8
19DOT1Q = 0x8100
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010020
21
22class TestSpan(VppTestCase):
23 """ SPAN Test Case """
24
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010025 @classmethod
26 def setUpClass(cls):
27 super(TestSpan, cls).setUpClass()
Eyal Bari001fd402017-07-16 09:34:53 +030028 # Test variables
29 cls.hosts_nr = 10 # Number of hosts
30 cls.pkts_per_burst = 257 # Number of packets per burst
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010031 # create 3 pg interfaces
Eyal Bari001fd402017-07-16 09:34:53 +030032 cls.create_pg_interfaces(range(3))
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010033
Eyal Bari001fd402017-07-16 09:34:53 +030034 cls.bd_id = 55
35 cls.sub_if = VppDot1QSubint(cls, cls.pg0, 100)
36 cls.dst_sub_if = VppDot1QSubint(cls, cls.pg2, 300)
37 cls.dst_sub_if.set_vtr(L2_VTR_OP.L2_POP_1, tag=300)
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010038 # packet flows mapping pg0 -> pg1, pg2 -> pg3, etc.
Eyal Bari001fd402017-07-16 09:34:53 +030039 cls.flows = dict()
40 cls.flows[cls.pg0] = [cls.pg1]
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010041
42 # packet sizes
Eyal Bari001fd402017-07-16 09:34:53 +030043 cls.pg_if_packet_sizes = [64, 512] # , 1518, 9018]
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010044
Eyal Bari001fd402017-07-16 09:34:53 +030045 cls.interfaces = list(cls.pg_interfaces)
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010046
47 # Create host MAC and IPv4 lists
Eyal Bari001fd402017-07-16 09:34:53 +030048 # cls.MY_MACS = dict()
49 # cls.MY_IP4S = dict()
50 cls.create_host_lists(cls.hosts_nr)
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010051
52 # setup all interfaces
Eyal Bari001fd402017-07-16 09:34:53 +030053 for i in cls.interfaces:
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010054 i.admin_up()
55 i.config_ip4()
56 i.resolve_arp()
57
Eyal Bari001fd402017-07-16 09:34:53 +030058 cls.vxlan = cls.vapi.vxlan_add_del_tunnel(
59 src_addr=cls.pg2.local_ip4n,
60 dst_addr=cls.pg2.remote_ip4n,
61 vni=1111,
62 is_add=1)
63
64 def setUp(self):
65 super(TestSpan, self).setUp()
66 self.reset_packet_infos()
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010067
68 def tearDown(self):
69 super(TestSpan, self).tearDown()
Eyal Bari001fd402017-07-16 09:34:53 +030070 if not self.vpp_dead:
71 self.logger.info(self.vapi.ppcli("show interface span"))
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +010072
Eyal Bari001fd402017-07-16 09:34:53 +030073 def xconnect(self, a, b, is_add=1):
74 self.vapi.sw_interface_set_l2_xconnect(a, b, enable=is_add)
75 self.vapi.sw_interface_set_l2_xconnect(b, a, enable=is_add)
76
77 def bridge(self, sw_if_index, is_add=1):
78 self.vapi.sw_interface_set_l2_bridge(
79 sw_if_index, bd_id=self.bd_id, enable=is_add)
80
81 def _remove_tag(self, packet, vlan, tag_type):
82 self.assertEqual(packet.type, tag_type)
83 payload = packet.payload
84 self.assertEqual(payload.vlan, vlan)
85 inner_type = payload.type
86 payload = payload.payload
87 packet.remove_payload()
88 packet.add_payload(payload)
89 packet.type = inner_type
90
91 def remove_tags(self, packet, tags):
92 for t in tags:
93 self._remove_tag(packet, t.vlan, t.dot1)
94 return packet
95
96 def decap_gre(self, pkt):
97 """
98 Decapsulate the original payload frame by removing GRE header
99 """
100 self.assertEqual(pkt[Ether].src, self.pg2.local_mac)
101 self.assertEqual(pkt[Ether].dst, self.pg2.remote_mac)
102
103 self.assertEqual(pkt[IP].src, self.pg2.local_ip4)
104 self.assertEqual(pkt[IP].dst, self.pg2.remote_ip4)
105
106 return pkt[GRE].payload
107
108 def decap_vxlan(self, pkt):
109 """
110 Decapsulate the original payload frame by removing VXLAN header
111 """
112 self.assertEqual(pkt[Ether].src, self.pg2.local_mac)
113 self.assertEqual(pkt[Ether].dst, self.pg2.remote_mac)
114
115 self.assertEqual(pkt[IP].src, self.pg2.local_ip4)
116 self.assertEqual(pkt[IP].dst, self.pg2.remote_ip4)
117
118 return pkt[VXLAN].payload
119
120 @classmethod
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100121 def create_host_lists(self, count):
122 """ Method to create required number of MAC and IPv4 addresses.
123 Create required number of host MAC addresses and distribute them among
124 interfaces. Create host IPv4 address for every host MAC address too.
125
126 :param count: Number of hosts to create MAC and IPv4 addresses for.
127 """
128 # mapping between packet-generator index and lists of test hosts
129 self.hosts_by_pg_idx = dict()
130
131 for pg_if in self.pg_interfaces:
132 # self.MY_MACS[i.sw_if_index] = []
133 # self.MY_IP4S[i.sw_if_index] = []
134 self.hosts_by_pg_idx[pg_if.sw_if_index] = []
135 hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
136 for j in range(0, count):
137 host = Host(
138 "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
139 "172.17.1%02x.%u" % (pg_if.sw_if_index, j))
140 hosts.append(host)
141
Eyal Bari001fd402017-07-16 09:34:53 +0300142 def create_stream(self, src_if, packet_sizes, do_dot1=False):
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100143 pkts = []
Eyal Bari001fd402017-07-16 09:34:53 +0300144 for i in range(0, self.pkts_per_burst):
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100145 dst_if = self.flows[src_if][0]
Klement Sekeradab231a2016-12-21 08:50:14 +0100146 pkt_info = self.create_packet_info(src_if, dst_if)
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100147 payload = self.info_to_payload(pkt_info)
148 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
149 IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4) /
150 UDP(sport=1234, dport=1234) /
151 Raw(payload))
Eyal Bari001fd402017-07-16 09:34:53 +0300152 if do_dot1:
153 p = self.sub_if.add_dot1_layer(p)
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100154 pkt_info.data = p.copy()
155 size = packet_sizes[(i / 2) % len(packet_sizes)]
156 self.extend_packet(p, size)
157 pkts.append(p)
158 return pkts
159
160 def verify_capture(self, dst_if, capture_pg1, capture_pg2):
161 last_info = dict()
162 for i in self.interfaces:
163 last_info[i.sw_if_index] = None
164 dst_sw_if_index = dst_if.sw_if_index
Klement Sekera82130452017-01-12 03:39:42 +0100165 self.assertEqual(
Klement Sekerada505f62017-01-04 12:58:53 +0100166 len(capture_pg1),
167 len(capture_pg2),
168 "Different number of outgoing and mirrored packets : %u != %u" %
169 (len(capture_pg1),
170 len(capture_pg2)))
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100171 for pkt_pg1, pkt_pg2 in zip(capture_pg1, capture_pg2):
172 try:
173 ip1 = pkt_pg1[IP]
174 udp1 = pkt_pg1[UDP]
175 raw1 = pkt_pg1[Raw]
176
177 if pkt_pg1[Ether] != pkt_pg2[Ether]:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100178 self.logger.error("Different ethernet header of "
179 "outgoing and mirrored packet")
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100180 raise
181 if ip1 != pkt_pg2[IP]:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100182 self.logger.error(
183 "Different ip header of outgoing and mirrored packet")
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100184 raise
185 if udp1 != pkt_pg2[UDP]:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100186 self.logger.error(
187 "Different udp header of outgoing and mirrored packet")
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100188 raise
189 if raw1 != pkt_pg2[Raw]:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100190 self.logger.error(
191 "Different raw data of outgoing and mirrored packet")
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100192 raise
193
194 payload_info = self.payload_to_info(str(raw1))
195 packet_index = payload_info.index
196 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekera7bb873a2016-11-18 07:38:42 +0100197 self.logger.debug(
198 "Got packet on port %s: src=%u (id=%u)" %
199 (dst_if.name, payload_info.src, packet_index))
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100200 next_info = self.get_next_packet_info_for_interface2(
201 payload_info.src, dst_sw_if_index,
202 last_info[payload_info.src])
203 last_info[payload_info.src] = next_info
204 self.assertTrue(next_info is not None)
205 self.assertEqual(packet_index, next_info.index)
206 saved_packet = next_info.data
207 # Check standard fields
208 self.assertEqual(ip1.src, saved_packet[IP].src)
209 self.assertEqual(ip1.dst, saved_packet[IP].dst)
210 self.assertEqual(udp1.sport, saved_packet[UDP].sport)
211 self.assertEqual(udp1.dport, saved_packet[UDP].dport)
212 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100213 self.logger.error("Unexpected or invalid packets:")
214 self.logger.error(ppp("pg1 packet:", pkt_pg1))
215 self.logger.error(ppp("pg2 packet:", pkt_pg2))
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100216 raise
217 for i in self.interfaces:
218 remaining_packet = self.get_next_packet_info_for_interface2(
219 i, dst_sw_if_index, last_info[i.sw_if_index])
220 self.assertTrue(remaining_packet is None,
221 "Port %u: Packet expected from source %u didn't"
222 " arrive" % (dst_sw_if_index, i.sw_if_index))
223
Eyal Bari001fd402017-07-16 09:34:53 +0300224 def test_device_span(self):
225 """ SPAN device rx mirror test
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100226
227 Test scenario:
228 1. config
229 3 interfaces, pg0 l2xconnected with pg1
Klement Sekera7bb873a2016-11-18 07:38:42 +0100230 2. sending l2 eth packets between 2 interfaces (pg0, pg1) and
231 mirrored to pg2
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100232 64B, 512B, 1518B, 9018B (ether_size)
233 burst of packets per interface
234 """
235
Eyal Bari001fd402017-07-16 09:34:53 +0300236 # Create bi-directional cross-connects between pg0 and pg1
237 self.xconnect(self.pg0.sw_if_index, self.pg1.sw_if_index)
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100238 # Create incoming packet streams for packet-generator interfaces
239 pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes)
240 self.pg0.add_stream(pkts)
241
Eyal Bari001fd402017-07-16 09:34:53 +0300242 # Enable SPAN on pg0 (mirrored to pg2)
243 self.vapi.sw_interface_span_enable_disable(
244 self.pg0.sw_if_index, self.pg2.sw_if_index)
245
246 self.logger.info(self.vapi.ppcli("show interface span"))
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100247 # Enable packet capturing and start packet sending
248 self.pg_enable_capture(self.pg_interfaces)
249 self.pg_start()
250
251 # Verify packets outgoing packet streams on mirrored interface (pg2)
Klement Sekera7bb873a2016-11-18 07:38:42 +0100252 self.logger.info("Verifying capture on interfaces %s and %s" %
253 (self.pg1.name, self.pg2.name))
Klement Sekeradab231a2016-12-21 08:50:14 +0100254 pg2_expected = self.get_packet_count_for_if_idx(self.pg1.sw_if_index)
255 self.verify_capture(
256 self.pg1,
257 self.pg1.get_capture(),
258 self.pg2.get_capture(pg2_expected))
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100259
Eyal Bari001fd402017-07-16 09:34:53 +0300260 # Disable SPAN on pg0 (mirrored to pg2)
261 self.vapi.sw_interface_span_enable_disable(
262 self.pg0.sw_if_index, self.pg2.sw_if_index, state=0)
263 self.xconnect(self.pg0.sw_if_index, self.pg1.sw_if_index, is_add=0)
264
265 def test_span_l2_rx(self):
266 """ SPAN l2 rx mirror test """
267
268 self.sub_if.admin_up()
269
270 self.bridge(self.pg2.sw_if_index)
271 # Create bi-directional cross-connects between pg0 and pg1
272 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index)
273 # Create incoming packet streams for packet-generator interfaces
274 pkts = self.create_stream(
275 self.pg0, self.pg_if_packet_sizes, do_dot1=True)
276 self.pg0.add_stream(pkts)
277
278 # Enable SPAN on pg0 (mirrored to pg2)
279 self.vapi.sw_interface_span_enable_disable(
280 self.sub_if.sw_if_index, self.pg2.sw_if_index, is_l2=1)
281
282 self.logger.info(self.vapi.ppcli("show interface span"))
283 # Enable packet capturing and start packet sending
284 self.pg_enable_capture(self.pg_interfaces)
285 self.pg_start()
286
287 # Verify packets outgoing packet streams on mirrored interface (pg2)
288 self.logger.info("Verifying capture on interfaces %s and %s" %
289 (self.pg1.name, self.pg2.name))
290 pg2_expected = self.get_packet_count_for_if_idx(self.pg1.sw_if_index)
291 pg1_pkts = self.pg1.get_capture()
292 pg2_pkts = self.pg2.get_capture(pg2_expected)
293 self.verify_capture(
294 self.pg1,
295 pg1_pkts,
296 pg2_pkts)
297
298 self.bridge(self.pg2.sw_if_index, is_add=0)
299 # Disable SPAN on pg0 (mirrored to pg2)
300 self.vapi.sw_interface_span_enable_disable(
301 self.sub_if.sw_if_index, self.pg2.sw_if_index, state=0, is_l2=1)
302 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0)
303
304 def test_span_l2_rx_dst_vxlan(self):
305 """ SPAN l2 rx mirror into vxlan test """
306
307 self.sub_if.admin_up()
308 self.vapi.sw_interface_set_flags(self.vxlan.sw_if_index,
309 admin_up_down=1)
310
311 self.bridge(self.vxlan.sw_if_index, is_add=1)
312 # Create bi-directional cross-connects between pg0 and pg1
313 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index)
314 # Create incoming packet streams for packet-generator interfaces
315 pkts = self.create_stream(
316 self.pg0, self.pg_if_packet_sizes, do_dot1=True)
317 self.pg0.add_stream(pkts)
318
319 # Enable SPAN on pg0 sub if (mirrored to vxlan)
320 self.vapi.sw_interface_span_enable_disable(
321 self.sub_if.sw_if_index, self.vxlan.sw_if_index, is_l2=1)
322
323 self.logger.info(self.vapi.ppcli("show interface span"))
324 # Enable packet capturing and start packet sending
325 self.pg_enable_capture(self.pg_interfaces)
326 self.pg_start()
327
328 # Verify packets outgoing packet streams on mirrored interface (pg2)
329 self.logger.info("Verifying capture on interfaces %s and %s" %
330 (self.pg1.name, self.pg2.name))
331 pg2_expected = self.get_packet_count_for_if_idx(self.pg1.sw_if_index)
332 pg1_pkts = self.pg1.get_capture()
333 pg2_pkts = [self.decap_vxlan(p)
334 for p in self.pg2.get_capture(pg2_expected)]
335 self.verify_capture(
336 self.pg1,
337 pg1_pkts,
338 pg2_pkts)
339
340 self.bridge(self.vxlan.sw_if_index, is_add=0)
341 # Disable SPAN on pg0 sub if (mirrored to vxlan)
342 self.vapi.sw_interface_span_enable_disable(
343 self.sub_if.sw_if_index, self.vxlan.sw_if_index, state=0, is_l2=1)
344 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0)
345
346 def test_span_l2_rx_dst_gre_subif_vtr(self):
347 """ SPAN l2 rx mirror into gre-subif+vtr """
348
349 self.sub_if.admin_up()
350
351 gre_if = VppGreInterface(self, self.pg2.local_ip4,
352 self.pg2.remote_ip4,
353 is_teb=1)
354
355 gre_if.add_vpp_config()
356 gre_if.admin_up()
357
358 gre_sub_if = VppDot1QSubint(self, gre_if, 500)
359 gre_sub_if.set_vtr(L2_VTR_OP.L2_POP_1, tag=500)
360 gre_sub_if.admin_up()
361
362 self.bridge(gre_sub_if.sw_if_index)
363 # Create bi-directional cross-connects between pg0 and pg1
364 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=1)
365
366 # Create incoming packet streams for packet-generator interfaces
367 pkts = self.create_stream(
368 self.pg0, self.pg_if_packet_sizes, do_dot1=True)
369 self.pg0.add_stream(pkts)
370
371 self.vapi.sw_interface_span_enable_disable(
372 self.sub_if.sw_if_index, gre_sub_if.sw_if_index, is_l2=1)
373
374 # Enable packet capturing and start packet sending
375 self.pg_enable_capture(self.pg_interfaces)
376 self.pg_start()
377
378 # Verify packets outgoing packet streams on mirrored interface (pg2)
379 self.logger.info("Verifying capture on interfaces %s and %s" %
380 (self.pg1.name, self.pg2.name))
381 pg2_expected = self.get_packet_count_for_if_idx(self.pg1.sw_if_index)
382 pg1_pkts = self.pg1.get_capture()
383 pg2_pkts = self.pg2.get_capture(pg2_expected)
384 pg2_decaped = [self.remove_tags(self.decap_gre(
385 p), [Tag(dot1=DOT1Q, vlan=500)]) for p in pg2_pkts]
386 self.verify_capture(
387 self.pg1,
388 pg1_pkts,
389 pg2_decaped)
390
391 self.bridge(gre_sub_if.sw_if_index, is_add=0)
392 # Disable SPAN on pg0 sub if
393 self.vapi.sw_interface_span_enable_disable(
394 self.sub_if.sw_if_index, gre_sub_if.sw_if_index, state=0,
395 is_l2=1)
396 gre_if.remove_vpp_config()
397 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0)
398
399 def test_span_l2_rx_dst_vtr(self):
400 """ SPAN l2 rx mirror into subif+vtr """
401
402 self.sub_if.admin_up()
403 self.dst_sub_if.admin_up()
404
405 self.bridge(self.dst_sub_if.sw_if_index)
406 # Create bi-directional cross-connects between pg0 and pg1
407 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=1)
408
409 # Create incoming packet streams for packet-generator interfaces
410 pkts = self.create_stream(
411 self.pg0, self.pg_if_packet_sizes, do_dot1=True)
412 self.pg0.add_stream(pkts)
413
414 self.vapi.sw_interface_span_enable_disable(
415 self.sub_if.sw_if_index, self.dst_sub_if.sw_if_index, is_l2=1)
416
417 # Enable packet capturing and start packet sending
418 self.pg_enable_capture(self.pg_interfaces)
419 self.pg_start()
420
421 # Verify packets outgoing packet streams on mirrored interface (pg2)
422 self.logger.info("Verifying capture on interfaces %s and %s" %
423 (self.pg1.name, self.pg2.name))
424 pg2_expected = self.get_packet_count_for_if_idx(self.pg1.sw_if_index)
425 pg1_pkts = self.pg1.get_capture()
426 pg2_pkts = self.pg2.get_capture(pg2_expected)
427 pg2_untagged = [self.remove_tags(p, [Tag(dot1=DOT1Q, vlan=300)])
428 for p in pg2_pkts]
429 self.verify_capture(
430 self.pg1,
431 pg1_pkts,
432 pg2_untagged)
433
434 self.bridge(self.dst_sub_if.sw_if_index, is_add=0)
435 # Disable SPAN on pg0 sub if (mirrored to vxlan)
436 self.vapi.sw_interface_span_enable_disable(
437 self.sub_if.sw_if_index, self.dst_sub_if.sw_if_index, state=0,
438 is_l2=1)
439 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0)
440
441 def test_l2_tx_span(self):
442 """ SPAN l2 tx mirror test """
443
444 self.sub_if.admin_up()
445 self.bridge(self.pg2.sw_if_index)
446 # Create bi-directional cross-connects between pg0 and pg1
447 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index)
448 # Create incoming packet streams for packet-generator interfaces
449 pkts = self.create_stream(
450 self.pg0, self.pg_if_packet_sizes, do_dot1=True)
451 self.pg0.add_stream(pkts)
452
453 # Enable SPAN on pg0 (mirrored to pg2)
454 self.vapi.sw_interface_span_enable_disable(
455 self.pg1.sw_if_index, self.pg2.sw_if_index, is_l2=1, state=2)
456
457 self.logger.info(self.vapi.ppcli("show interface span"))
458 # Enable packet capturing and start packet sending
459 self.pg_enable_capture(self.pg_interfaces)
460 self.pg_start()
461
462 # Verify packets outgoing packet streams on mirrored interface (pg2)
463 self.logger.info("Verifying capture on interfaces %s and %s" %
464 (self.pg1.name, self.pg2.name))
465 pg2_expected = self.get_packet_count_for_if_idx(self.pg1.sw_if_index)
466 pg1_pkts = self.pg1.get_capture()
467 pg2_pkts = self.pg2.get_capture(pg2_expected)
468 self.verify_capture(
469 self.pg1,
470 pg1_pkts,
471 pg2_pkts)
472
473 self.bridge(self.pg2.sw_if_index, is_add=0)
474 # Disable SPAN on pg0 (mirrored to pg2)
475 self.vapi.sw_interface_span_enable_disable(
476 self.pg1.sw_if_index, self.pg2.sw_if_index, state=0, is_l2=1)
477 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0)
478
Pavel Kotucekf6e3dc42016-11-04 09:58:01 +0100479
480if __name__ == '__main__':
481 unittest.main(testRunner=VppTestRunner)