ipfix-export: support creating multiple exporters
[vpp.git] / test / test_ipsec_spd_flow_cache.py
1 import socket
2 import unittest
3
4 from util import ppp
5 from framework import VppTestRunner
6 from template_ipsec import SpdFlowCacheTemplate
7
8
9 class SpdFlowCacheOutbound(SpdFlowCacheTemplate):
10     # Override setUpConstants to enable outbound flow cache in config
11     @classmethod
12     def setUpConstants(cls):
13         super(SpdFlowCacheOutbound, cls).setUpConstants()
14         cls.vpp_cmdline.extend(["ipsec", "{",
15                                 "ipv4-outbound-spd-flow-cache on",
16                                 "}"])
17         cls.logger.info("VPP modified cmdline is %s" % " "
18                         .join(cls.vpp_cmdline))
19
20
21 class IPSec4SpdTestCaseAdd(SpdFlowCacheOutbound):
22     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
23         (add rule)"""
24     def test_ipsec_spd_outbound_add(self):
25         # In this test case, packets in IPv4 FWD path are configured
26         # to go through IPSec outbound SPD policy lookup.
27         # 2 SPD rules (1 HIGH and 1 LOW) are added.
28         # High priority rule action is set to BYPASS.
29         # Low priority rule action is set to DISCARD.
30         # Traffic sent on pg0 interface should match high priority
31         # rule and should be sent out on pg1 interface.
32         self.create_interfaces(2)
33         pkt_count = 5
34         self.spd_create_and_intf_add(1, [self.pg1])
35         policy_0 = self.spd_add_rem_policy(  # outbound, priority 10
36             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
37             is_out=1, priority=10, policy_type="bypass")
38         policy_1 = self.spd_add_rem_policy(  # outbound, priority 5
39             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
40             is_out=1, priority=5, policy_type="discard")
41
42         # check flow cache is empty before sending traffic
43         self.verify_num_outbound_flow_cache_entries(0)
44
45         # create the packet stream
46         packets = self.create_stream(self.pg0, self.pg1, pkt_count)
47         # add the stream to the source interface + enable capture
48         self.pg0.add_stream(packets)
49         self.pg0.enable_capture()
50         self.pg1.enable_capture()
51         # start the packet generator
52         self.pg_start()
53         # get capture
54         capture = self.pg1.get_capture()
55         for packet in capture:
56             try:
57                 self.logger.debug(ppp("SPD - Got packet:", packet))
58             except Exception:
59                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
60                 raise
61         self.logger.debug("SPD: Num packets: %s", len(capture.res))
62
63         # assert nothing captured on pg0
64         self.pg0.assert_nothing_captured()
65         # verify captured packets
66         self.verify_capture(self.pg0, self.pg1, capture)
67         # verify all policies matched the expected number of times
68         self.verify_policy_match(pkt_count, policy_0)
69         self.verify_policy_match(0, policy_1)
70         # check policy in SPD has been cached after traffic
71         # matched BYPASS rule in SPD
72         self.verify_num_outbound_flow_cache_entries(1)
73
74
75 class IPSec4SpdTestCaseRemove(SpdFlowCacheOutbound):
76     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
77         (remove rule)"""
78     def test_ipsec_spd_outbound_remove(self):
79         # In this test case, packets in IPv4 FWD path are configured
80         # to go through IPSec outbound SPD policy lookup.
81         # 2 SPD rules (1 HIGH and 1 LOW) are added.
82         # High priority rule action is set to BYPASS.
83         # Low priority rule action is set to DISCARD.
84         # High priority rule is then removed.
85         # Traffic sent on pg0 interface should match low priority
86         # rule and should be discarded after SPD lookup.
87         self.create_interfaces(2)
88         pkt_count = 5
89         self.spd_create_and_intf_add(1, [self.pg1])
90         policy_0 = self.spd_add_rem_policy(  # outbound, priority 10
91             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
92             is_out=1, priority=10, policy_type="bypass")
93         policy_1 = self.spd_add_rem_policy(  # outbound, priority 5
94             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
95             is_out=1, priority=5, policy_type="discard")
96
97         # check flow cache is empty before sending traffic
98         self.verify_num_outbound_flow_cache_entries(0)
99
100         # create the packet stream
101         packets = self.create_stream(self.pg0, self.pg1, pkt_count)
102         # add the stream to the source interface + enable capture
103         self.pg0.add_stream(packets)
104         self.pg0.enable_capture()
105         self.pg1.enable_capture()
106         # start the packet generator
107         self.pg_start()
108         # get capture
109         capture = self.pg1.get_capture()
110         for packet in capture:
111             try:
112                 self.logger.debug(ppp("SPD - Got packet:", packet))
113             except Exception:
114                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
115                 raise
116
117         # assert nothing captured on pg0
118         self.pg0.assert_nothing_captured()
119         # verify capture on pg1
120         self.logger.debug("SPD: Num packets: %s", len(capture.res))
121         self.verify_capture(self.pg0, self.pg1, capture)
122         # verify all policies matched the expected number of times
123         self.verify_policy_match(pkt_count, policy_0)
124         self.verify_policy_match(0, policy_1)
125         # check policy in SPD has been cached after traffic
126         # matched BYPASS rule in SPD
127         self.verify_num_outbound_flow_cache_entries(1)
128
129         # now remove the bypass rule
130         self.spd_add_rem_policy(  # outbound, priority 10
131             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
132             is_out=1, priority=10, policy_type="bypass",
133             remove=True)
134         # verify flow cache counter has been reset by rule removal
135         self.verify_num_outbound_flow_cache_entries(0)
136
137         # resend the same packets
138         self.pg0.add_stream(packets)
139         self.pg0.enable_capture()  # flush the old captures
140         self.pg1.enable_capture()
141         self.pg_start()
142         # assert nothing captured on pg0
143         self.pg0.assert_nothing_captured()
144         # all packets will be dropped by SPD rule
145         self.pg1.assert_nothing_captured()
146         # verify all policies matched the expected number of times
147         self.verify_policy_match(pkt_count, policy_0)
148         self.verify_policy_match(pkt_count, policy_1)
149         # previous stale entry in flow cache should have been overwritten,
150         # with one active entry
151         self.verify_num_outbound_flow_cache_entries(1)
152
153
154 class IPSec4SpdTestCaseReadd(SpdFlowCacheOutbound):
155     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
156         (add, remove, re-add)"""
157     def test_ipsec_spd_outbound_readd(self):
158         # In this test case, packets in IPv4 FWD path are configured
159         # to go through IPSec outbound SPD policy lookup.
160         # 2 SPD rules (1 HIGH and 1 LOW) are added.
161         # High priority rule action is set to BYPASS.
162         # Low priority rule action is set to DISCARD.
163         # Traffic sent on pg0 interface should match high priority
164         # rule and should be sent out on pg1 interface.
165         # High priority rule is then removed.
166         # Traffic sent on pg0 interface should match low priority
167         # rule and should be discarded after SPD lookup.
168         # Readd high priority rule.
169         # Traffic sent on pg0 interface should match high priority
170         # rule and should be sent out on pg1 interface.
171         self.create_interfaces(2)
172         pkt_count = 5
173         self.spd_create_and_intf_add(1, [self.pg1])
174         policy_0 = self.spd_add_rem_policy(  # outbound, priority 10
175             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
176             is_out=1, priority=10, policy_type="bypass")
177         policy_1 = self.spd_add_rem_policy(  # outbound, priority 5
178             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
179             is_out=1, priority=5, policy_type="discard")
180
181         # check flow cache is empty before sending traffic
182         self.verify_num_outbound_flow_cache_entries(0)
183
184         # create the packet stream
185         packets = self.create_stream(self.pg0, self.pg1, pkt_count)
186         # add the stream to the source interface + enable capture
187         self.pg0.add_stream(packets)
188         self.pg0.enable_capture()
189         self.pg1.enable_capture()
190         # start the packet generator
191         self.pg_start()
192         # get capture
193         capture = self.pg1.get_capture()
194         for packet in capture:
195             try:
196                 self.logger.debug(ppp("SPD - Got packet:", packet))
197             except Exception:
198                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
199                 raise
200         self.logger.debug("SPD: Num packets: %s", len(capture.res))
201
202         # assert nothing captured on pg0
203         self.pg0.assert_nothing_captured()
204         # verify capture on pg1
205         self.verify_capture(self.pg0, self.pg1, capture)
206         # verify all policies matched the expected number of times
207         self.verify_policy_match(pkt_count, policy_0)
208         self.verify_policy_match(0, policy_1)
209         # check policy in SPD has been cached after traffic
210         # matched BYPASS rule in SPD
211         self.verify_num_outbound_flow_cache_entries(1)
212
213         # now remove the bypass rule, leaving only the discard rule
214         self.spd_add_rem_policy(  # outbound, priority 10
215             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
216             is_out=1, priority=10, policy_type="bypass",
217             remove=True)
218         # verify flow cache counter has been reset by rule removal
219         self.verify_num_outbound_flow_cache_entries(0)
220
221         # resend the same packets
222         self.pg0.add_stream(packets)
223         self.pg0.enable_capture()  # flush the old captures
224         self.pg1.enable_capture()
225         self.pg_start()
226
227         # assert nothing captured on pg0
228         self.pg0.assert_nothing_captured()
229         # all packets will be dropped by SPD rule
230         self.pg1.assert_nothing_captured()
231         # verify all policies matched the expected number of times
232         self.verify_policy_match(pkt_count, policy_0)
233         self.verify_policy_match(pkt_count, policy_1)
234         # previous stale entry in flow cache should have been overwritten
235         self.verify_num_outbound_flow_cache_entries(1)
236
237         # now readd the bypass rule
238         policy_0 = self.spd_add_rem_policy(  # outbound, priority 10
239             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
240             is_out=1, priority=10, policy_type="bypass")
241         # verify flow cache counter has been reset by rule addition
242         self.verify_num_outbound_flow_cache_entries(0)
243
244         # resend the same packets
245         self.pg0.add_stream(packets)
246         self.pg0.enable_capture()  # flush the old captures
247         self.pg1.enable_capture()
248         self.pg_start()
249
250         # get capture
251         capture = self.pg1.get_capture(pkt_count)
252         for packet in capture:
253             try:
254                 self.logger.debug(ppp("SPD - Got packet:", packet))
255             except Exception:
256                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
257                 raise
258         self.logger.debug("SPD: Num packets: %s", len(capture.res))
259
260         # assert nothing captured on pg0
261         self.pg0.assert_nothing_captured()
262         # verify captured packets
263         self.verify_capture(self.pg0, self.pg1, capture)
264         # verify all policies matched the expected number of times
265         self.verify_policy_match(pkt_count, policy_0)
266         self.verify_policy_match(pkt_count, policy_1)
267         # previous stale entry in flow cache should have been overwritten
268         self.verify_num_outbound_flow_cache_entries(1)
269
270
271 class IPSec4SpdTestCaseMultiple(SpdFlowCacheOutbound):
272     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
273         (multiple interfaces, multiple rules)"""
274     def test_ipsec_spd_outbound_multiple(self):
275         # In this test case, packets in IPv4 FWD path are configured to go
276         # through IPSec outbound SPD policy lookup.
277         # Multiples rules on multiple interfaces are tested at the same time.
278         # 3x interfaces are configured, binding the same SPD to each.
279         # Each interface has 2 SPD rules (1 BYPASS and 1 DISCARD).
280         # On pg0 & pg1, the BYPASS rule is HIGH priority
281         # On pg2, the DISCARD rule is HIGH priority
282         # Traffic should be received on pg0 & pg1 and dropped on pg2.
283         self.create_interfaces(3)
284         pkt_count = 5
285         # bind SPD to all interfaces
286         self.spd_create_and_intf_add(1, self.pg_interfaces)
287         # add rules on all interfaces
288         policy_01 = self.spd_add_rem_policy(  # outbound, priority 10
289             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
290             is_out=1, priority=10, policy_type="bypass")
291         policy_02 = self.spd_add_rem_policy(  # outbound, priority 5
292             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
293             is_out=1, priority=5, policy_type="discard")
294
295         policy_11 = self.spd_add_rem_policy(  # outbound, priority 10
296             1, self.pg1, self.pg2, socket.IPPROTO_UDP,
297             is_out=1, priority=10, policy_type="bypass")
298         policy_12 = self.spd_add_rem_policy(  # outbound, priority 5
299             1, self.pg1, self.pg2, socket.IPPROTO_UDP,
300             is_out=1, priority=5, policy_type="discard")
301
302         policy_21 = self.spd_add_rem_policy(  # outbound, priority 5
303             1, self.pg2, self.pg0, socket.IPPROTO_UDP,
304             is_out=1, priority=5, policy_type="bypass")
305         policy_22 = self.spd_add_rem_policy(  # outbound, priority 10
306             1, self.pg2, self.pg0, socket.IPPROTO_UDP,
307             is_out=1, priority=10, policy_type="discard")
308
309         # check flow cache is empty (0 active elements) before sending traffic
310         self.verify_num_outbound_flow_cache_entries(0)
311
312         # create the packet streams
313         packets0 = self.create_stream(self.pg0, self.pg1, pkt_count)
314         packets1 = self.create_stream(self.pg1, self.pg2, pkt_count)
315         packets2 = self.create_stream(self.pg2, self.pg0, pkt_count)
316         # add the streams to the source interfaces
317         self.pg0.add_stream(packets0)
318         self.pg1.add_stream(packets1)
319         self.pg2.add_stream(packets2)
320         # enable capture on all interfaces
321         for pg in self.pg_interfaces:
322             pg.enable_capture()
323         # start the packet generator
324         self.pg_start()
325
326         # get captures
327         if_caps = []
328         for pg in [self.pg1, self.pg2]:  # we are expecting captures on pg1/pg2
329             if_caps.append(pg.get_capture())
330             for packet in if_caps[-1]:
331                 try:
332                     self.logger.debug(ppp("SPD - Got packet:", packet))
333                 except Exception:
334                     self.logger.error(
335                         ppp("Unexpected or invalid packet:", packet))
336                     raise
337         self.logger.debug("SPD: Num packets: %s", len(if_caps[0].res))
338         self.logger.debug("SPD: Num packets: %s", len(if_caps[1].res))
339
340         # verify captures that matched BYPASS rule
341         self.verify_capture(self.pg0, self.pg1, if_caps[0])
342         self.verify_capture(self.pg1, self.pg2, if_caps[1])
343         # verify that traffic to pg0 matched DISCARD rule and was dropped
344         self.pg0.assert_nothing_captured()
345         # verify all packets that were expected to match rules, matched
346         # pg0 -> pg1
347         self.verify_policy_match(pkt_count, policy_01)
348         self.verify_policy_match(0, policy_02)
349         # pg1 -> pg2
350         self.verify_policy_match(pkt_count, policy_11)
351         self.verify_policy_match(0, policy_12)
352         # pg2 -> pg0
353         self.verify_policy_match(0, policy_21)
354         self.verify_policy_match(pkt_count, policy_22)
355         # check that 3 matching policies in SPD have been cached
356         self.verify_num_outbound_flow_cache_entries(3)
357
358
359 class IPSec4SpdTestCaseOverwriteStale(SpdFlowCacheOutbound):
360     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
361         (overwrite stale entries)"""
362     def test_ipsec_spd_outbound_overwrite(self):
363         # The operation of the flow cache is setup so that the entire cache
364         # is invalidated when adding or removing an SPD policy rule.
365         # For performance, old cache entries are not zero'd, but remain
366         # in the table as "stale" entries. If a flow matches a stale entry,
367         # and the epoch count does NOT match the current count, the entry
368         # is overwritten.
369         # In this test, 3 active rules are created and matched to enter
370         # them into the flow cache.
371         # A single entry is removed to invalidate the entire cache.
372         # We then readd the rule and test that overwriting of the previous
373         # stale entries occurs as expected, and that the flow cache entry
374         # counter is updated correctly.
375         self.create_interfaces(3)
376         pkt_count = 2
377         # bind SPD to all interfaces
378         self.spd_create_and_intf_add(1, self.pg_interfaces)
379         # add output rules on all interfaces
380         # pg0 -> pg1
381         policy_0 = self.spd_add_rem_policy(  # outbound
382             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
383             is_out=1, priority=10, policy_type="bypass")
384         # pg1 -> pg2
385         policy_1 = self.spd_add_rem_policy(  # outbound
386             1, self.pg1, self.pg2, socket.IPPROTO_UDP,
387             is_out=1, priority=10, policy_type="bypass")
388         # pg2 -> pg0
389         policy_2 = self.spd_add_rem_policy(  # outbound
390             1, self.pg2, self.pg0, socket.IPPROTO_UDP,
391             is_out=1, priority=10, policy_type="discard")
392
393         # check flow cache is empty (0 active elements) before sending traffic
394         self.verify_num_outbound_flow_cache_entries(0)
395
396         # create the packet streams
397         packets0 = self.create_stream(self.pg0, self.pg1, pkt_count)
398         packets1 = self.create_stream(self.pg1, self.pg2, pkt_count)
399         packets2 = self.create_stream(self.pg2, self.pg0, pkt_count)
400         # add the streams to the source interfaces
401         self.pg0.add_stream(packets0)
402         self.pg1.add_stream(packets1)
403         self.pg2.add_stream(packets2)
404         # enable capture on all interfaces
405         for pg in self.pg_interfaces:
406             pg.enable_capture()
407         # start the packet generator
408         self.pg_start()
409
410         # get captures from ifs
411         if_caps = []
412         for pg in [self.pg1, self.pg2]:  # we are expecting captures on pg1/pg2
413             if_caps.append(pg.get_capture())
414             for packet in if_caps[-1]:
415                 try:
416                     self.logger.debug(ppp("SPD Add - Got packet:", packet))
417                 except Exception:
418                     self.logger.error(
419                         ppp("Unexpected or invalid packet:", packet))
420                     raise
421
422         # verify captures that matched BYPASS rules
423         self.verify_capture(self.pg0, self.pg1, if_caps[0])
424         self.verify_capture(self.pg1, self.pg2, if_caps[1])
425         # verify that traffic to pg0 matched DISCARD rule and was dropped
426         self.pg0.assert_nothing_captured()
427         # verify all policies matched the expected number of times
428         self.verify_policy_match(pkt_count, policy_0)
429         self.verify_policy_match(pkt_count, policy_1)
430         self.verify_policy_match(pkt_count, policy_2)
431         # check flow/policy match was cached for: 3x output policies
432         self.verify_num_outbound_flow_cache_entries(3)
433
434         # adding an inbound policy should not invalidate output flow cache
435         self.spd_add_rem_policy(  # inbound
436             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
437             is_out=0, priority=10, policy_type="bypass")
438         # check flow cache counter has not been reset
439         self.verify_num_outbound_flow_cache_entries(3)
440
441         # remove a bypass policy - flow cache counter will be reset, and
442         # there will be 3x stale entries in flow cache
443         self.spd_add_rem_policy(  # outbound
444             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
445             is_out=1, priority=10, policy_type="bypass",
446             remove=True)
447         # readd policy
448         policy_0 = self.spd_add_rem_policy(  # outbound
449             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
450             is_out=1, priority=10, policy_type="bypass")
451         # check counter was reset with flow cache invalidation
452         self.verify_num_outbound_flow_cache_entries(0)
453
454         # resend the same packets
455         self.pg0.add_stream(packets0)
456         self.pg1.add_stream(packets1)
457         self.pg2.add_stream(packets2)
458         for pg in self.pg_interfaces:
459             pg.enable_capture()  # flush previous captures
460         self.pg_start()
461
462         # get captures from ifs
463         if_caps = []
464         for pg in [self.pg1, self.pg2]:  # we are expecting captures on pg1/pg2
465             if_caps.append(pg.get_capture())
466             for packet in if_caps[-1]:
467                 try:
468                     self.logger.debug(ppp("SPD Add - Got packet:", packet))
469                 except Exception:
470                     self.logger.error(
471                         ppp("Unexpected or invalid packet:", packet))
472                     raise
473
474         # verify captures that matched BYPASS rules
475         self.verify_capture(self.pg0, self.pg1, if_caps[0])
476         self.verify_capture(self.pg1, self.pg2, if_caps[1])
477         # verify that traffic to pg0 matched DISCARD rule and was dropped
478         self.pg0.assert_nothing_captured()
479         # verify all policies matched the expected number of times
480         self.verify_policy_match(pkt_count, policy_0)
481         self.verify_policy_match(pkt_count*2, policy_1)
482         self.verify_policy_match(pkt_count*2, policy_2)
483         # we are overwriting 3x stale entries - check flow cache counter
484         # is correct
485         self.verify_num_outbound_flow_cache_entries(3)
486
487
488 class IPSec4SpdTestCaseCollision(SpdFlowCacheOutbound):
489     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
490         (hash collision)"""
491     # Override class setup to restrict vector size to 16 elements.
492     # This forces using only the lower 4 bits of the hash as a key,
493     # making hash collisions easy to find.
494     @classmethod
495     def setUpConstants(cls):
496         super(SpdFlowCacheOutbound, cls).setUpConstants()
497         cls.vpp_cmdline.extend(["ipsec", "{",
498                                 "ipv4-outbound-spd-flow-cache on",
499                                 "ipv4-outbound-spd-hash-buckets 16",
500                                 "}"])
501         cls.logger.info("VPP modified cmdline is %s" % " "
502                         .join(cls.vpp_cmdline))
503
504     def test_ipsec_spd_outbound_collision(self):
505         # The flow cache operation is setup to overwrite an entry
506         # if a hash collision occurs.
507         # In this test, 2 packets are configured that result in a
508         # hash with the same lower 4 bits.
509         # After the first packet is received, there should be one
510         # active entry in the flow cache.
511         # After the second packet with the same lower 4 bit hash
512         # is received, this should overwrite the same entry.
513         # Therefore there will still be a total of one (1) entry,
514         # in the flow cache with two matching policies.
515         # crc32_supported() method is used to check cpu for crc32
516         # intrinsic support for hashing.
517         # If crc32 is not supported, we fall back to clib_xxhash()
518         self.create_interfaces(3)
519         pkt_count = 5
520         # bind SPD to all interfaces
521         self.spd_create_and_intf_add(1, self.pg_interfaces)
522         # add rules
523         policy_0 = self.spd_add_rem_policy(  # outbound, priority 10
524             1, self.pg1, self.pg2, socket.IPPROTO_UDP,
525             is_out=1, priority=10, policy_type="bypass")
526         policy_1 = self.spd_add_rem_policy(  # outbound, priority 10
527             1, self.pg2, self.pg0, socket.IPPROTO_UDP,
528             is_out=1, priority=10, policy_type="bypass")
529
530         # check flow cache is empty (0 active elements) before sending traffic
531         self.verify_num_outbound_flow_cache_entries(0)
532
533         # create the packet streams generating collision on last 4 bits
534         if self.crc32_supported():
535             # packet hashes to:
536             # 432c99c2
537             packets1 = self.create_stream(self.pg1, self.pg2, pkt_count, 1, 1)
538             # 31f8f3f2
539             packets2 = self.create_stream(self.pg2, self.pg0, pkt_count, 6, 6)
540         else:  # clib_xxhash
541             # ec3a258551bc0306
542             packets1 = self.create_stream(self.pg1, self.pg2, pkt_count, 2, 2)
543             # 61fee526d18d7a6
544             packets2 = self.create_stream(self.pg2, self.pg0, pkt_count, 3, 3)
545
546         # add the streams to the source interfaces
547         self.pg1.add_stream(packets1)
548         self.pg2.add_stream(packets2)
549         # enable capture on all interfaces
550         for pg in self.pg_interfaces:
551             pg.enable_capture()
552         # start the packet generator
553         self.pg_start()
554
555         # get captures from ifs - the proper pkt_count of packets was saved by
556         # create_packet_info() based on dst_if parameter
557         if_caps = []
558         for pg in [self.pg2, self.pg0]:  # we are expecting captures on pg2/pg0
559             if_caps.append(pg.get_capture())
560             for packet in if_caps[-1]:
561                 try:
562                     self.logger.debug(ppp(
563                         "SPD - Got packet:", packet))
564                 except Exception:
565                     self.logger.error(ppp(
566                         "Unexpected or invalid packet:", packet))
567                     raise
568         self.logger.debug("SPD: Num packets: %s", len(if_caps[0].res))
569         self.logger.debug("SPD: Num packets: %s", len(if_caps[1].res))
570
571         # verify captures that matched BYPASS rule
572         self.verify_capture(self.pg1, self.pg2, if_caps[0])
573         self.verify_capture(self.pg2, self.pg0, if_caps[1])
574         # verify all packets that were expected to match rules, matched
575         self.verify_policy_match(pkt_count, policy_0)
576         self.verify_policy_match(pkt_count, policy_1)
577         # we have matched 2 policies, but due to the hash collision
578         # one active entry is expected
579         self.verify_num_outbound_flow_cache_entries(1)
580
581
582 if __name__ == '__main__':
583     unittest.main(testRunner=VppTestRunner)