54571c6741ab42f246c299230dfb4bd389bb787f
[vpp.git] / test / test_ipsec_spd_flow_cache_output.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         # interfaces bound to an SPD, will by default drop inbound
310         # traffic with no matching policies. add catch-all inbound
311         # bypass rule to SPD:
312         self.spd_add_rem_policy(  # inbound, all interfaces
313             1, None, None, socket.IPPROTO_UDP, is_out=0, priority=10,
314             policy_type="bypass", all_ips=True)
315
316         # check flow cache is empty (0 active elements) before sending traffic
317         self.verify_num_outbound_flow_cache_entries(0)
318
319         # create the packet streams
320         packets0 = self.create_stream(self.pg0, self.pg1, pkt_count)
321         packets1 = self.create_stream(self.pg1, self.pg2, pkt_count)
322         packets2 = self.create_stream(self.pg2, self.pg0, pkt_count)
323         # add the streams to the source interfaces
324         self.pg0.add_stream(packets0)
325         self.pg1.add_stream(packets1)
326         self.pg2.add_stream(packets2)
327         # enable capture on all interfaces
328         for pg in self.pg_interfaces:
329             pg.enable_capture()
330         # start the packet generator
331         self.pg_start()
332
333         # get captures
334         if_caps = []
335         for pg in [self.pg1, self.pg2]:  # we are expecting captures on pg1/pg2
336             if_caps.append(pg.get_capture())
337             for packet in if_caps[-1]:
338                 try:
339                     self.logger.debug(ppp("SPD - Got packet:", packet))
340                 except Exception:
341                     self.logger.error(
342                         ppp("Unexpected or invalid packet:", packet))
343                     raise
344         self.logger.debug("SPD: Num packets: %s", len(if_caps[0].res))
345         self.logger.debug("SPD: Num packets: %s", len(if_caps[1].res))
346
347         # verify captures that matched BYPASS rule
348         self.verify_capture(self.pg0, self.pg1, if_caps[0])
349         self.verify_capture(self.pg1, self.pg2, if_caps[1])
350         # verify that traffic to pg0 matched DISCARD rule and was dropped
351         self.pg0.assert_nothing_captured()
352         # verify all packets that were expected to match rules, matched
353         # pg0 -> pg1
354         self.verify_policy_match(pkt_count, policy_01)
355         self.verify_policy_match(0, policy_02)
356         # pg1 -> pg2
357         self.verify_policy_match(pkt_count, policy_11)
358         self.verify_policy_match(0, policy_12)
359         # pg2 -> pg0
360         self.verify_policy_match(0, policy_21)
361         self.verify_policy_match(pkt_count, policy_22)
362         # check that 3 matching policies in SPD have been cached
363         self.verify_num_outbound_flow_cache_entries(3)
364
365
366 class IPSec4SpdTestCaseOverwriteStale(SpdFlowCacheOutbound):
367     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
368         (overwrite stale entries)"""
369     def test_ipsec_spd_outbound_overwrite(self):
370         # The operation of the flow cache is setup so that the entire cache
371         # is invalidated when adding or removing an SPD policy rule.
372         # For performance, old cache entries are not zero'd, but remain
373         # in the table as "stale" entries. If a flow matches a stale entry,
374         # and the epoch count does NOT match the current count, the entry
375         # is overwritten.
376         # In this test, 3 active rules are created and matched to enter
377         # them into the flow cache.
378         # A single entry is removed to invalidate the entire cache.
379         # We then readd the rule and test that overwriting of the previous
380         # stale entries occurs as expected, and that the flow cache entry
381         # counter is updated correctly.
382         self.create_interfaces(3)
383         pkt_count = 2
384         # bind SPD to all interfaces
385         self.spd_create_and_intf_add(1, self.pg_interfaces)
386         # add output rules on all interfaces
387         # pg0 -> pg1
388         policy_0 = self.spd_add_rem_policy(  # outbound
389             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
390             is_out=1, priority=10, policy_type="bypass")
391         # pg1 -> pg2
392         policy_1 = self.spd_add_rem_policy(  # outbound
393             1, self.pg1, self.pg2, socket.IPPROTO_UDP,
394             is_out=1, priority=10, policy_type="bypass")
395         # pg2 -> pg0
396         policy_2 = self.spd_add_rem_policy(  # outbound
397             1, self.pg2, self.pg0, socket.IPPROTO_UDP,
398             is_out=1, priority=10, policy_type="discard")
399
400         # interfaces bound to an SPD, will by default drop inbound
401         # traffic with no matching policies. add catch-all inbound
402         # bypass rule to SPD:
403         self.spd_add_rem_policy(  # inbound, all interfaces
404             1, None, None, socket.IPPROTO_UDP, is_out=0, priority=10,
405             policy_type="bypass", all_ips=True)
406
407         # check flow cache is empty (0 active elements) before sending traffic
408         self.verify_num_outbound_flow_cache_entries(0)
409
410         # create the packet streams
411         packets0 = self.create_stream(self.pg0, self.pg1, pkt_count)
412         packets1 = self.create_stream(self.pg1, self.pg2, pkt_count)
413         packets2 = self.create_stream(self.pg2, self.pg0, pkt_count)
414         # add the streams to the source interfaces
415         self.pg0.add_stream(packets0)
416         self.pg1.add_stream(packets1)
417         self.pg2.add_stream(packets2)
418         # enable capture on all interfaces
419         for pg in self.pg_interfaces:
420             pg.enable_capture()
421         # start the packet generator
422         self.pg_start()
423
424         # get captures from ifs
425         if_caps = []
426         for pg in [self.pg1, self.pg2]:  # we are expecting captures on pg1/pg2
427             if_caps.append(pg.get_capture())
428             for packet in if_caps[-1]:
429                 try:
430                     self.logger.debug(ppp("SPD Add - Got packet:", packet))
431                 except Exception:
432                     self.logger.error(
433                         ppp("Unexpected or invalid packet:", packet))
434                     raise
435
436         # verify captures that matched BYPASS rules
437         self.verify_capture(self.pg0, self.pg1, if_caps[0])
438         self.verify_capture(self.pg1, self.pg2, if_caps[1])
439         # verify that traffic to pg0 matched DISCARD rule and was dropped
440         self.pg0.assert_nothing_captured()
441         # verify all policies matched the expected number of times
442         self.verify_policy_match(pkt_count, policy_0)
443         self.verify_policy_match(pkt_count, policy_1)
444         self.verify_policy_match(pkt_count, policy_2)
445         # check flow/policy match was cached for: 3x output policies
446         self.verify_num_outbound_flow_cache_entries(3)
447
448         # adding an inbound policy should not invalidate output flow cache
449         self.spd_add_rem_policy(  # inbound
450             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
451             is_out=0, priority=10, policy_type="bypass")
452         # check flow cache counter has not been reset
453         self.verify_num_outbound_flow_cache_entries(3)
454
455         # remove a bypass policy - flow cache counter will be reset, and
456         # there will be 3x stale entries in flow cache
457         self.spd_add_rem_policy(  # outbound
458             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
459             is_out=1, priority=10, policy_type="bypass",
460             remove=True)
461         # readd policy
462         policy_0 = self.spd_add_rem_policy(  # outbound
463             1, self.pg0, self.pg1, socket.IPPROTO_UDP,
464             is_out=1, priority=10, policy_type="bypass")
465         # check counter was reset with flow cache invalidation
466         self.verify_num_outbound_flow_cache_entries(0)
467
468         # resend the same packets
469         self.pg0.add_stream(packets0)
470         self.pg1.add_stream(packets1)
471         self.pg2.add_stream(packets2)
472         for pg in self.pg_interfaces:
473             pg.enable_capture()  # flush previous captures
474         self.pg_start()
475
476         # get captures from ifs
477         if_caps = []
478         for pg in [self.pg1, self.pg2]:  # we are expecting captures on pg1/pg2
479             if_caps.append(pg.get_capture())
480             for packet in if_caps[-1]:
481                 try:
482                     self.logger.debug(ppp("SPD Add - Got packet:", packet))
483                 except Exception:
484                     self.logger.error(
485                         ppp("Unexpected or invalid packet:", packet))
486                     raise
487
488         # verify captures that matched BYPASS rules
489         self.verify_capture(self.pg0, self.pg1, if_caps[0])
490         self.verify_capture(self.pg1, self.pg2, if_caps[1])
491         # verify that traffic to pg0 matched DISCARD rule and was dropped
492         self.pg0.assert_nothing_captured()
493         # verify all policies matched the expected number of times
494         self.verify_policy_match(pkt_count, policy_0)
495         self.verify_policy_match(pkt_count*2, policy_1)
496         self.verify_policy_match(pkt_count*2, policy_2)
497         # we are overwriting 3x stale entries - check flow cache counter
498         # is correct
499         self.verify_num_outbound_flow_cache_entries(3)
500
501
502 class IPSec4SpdTestCaseCollision(SpdFlowCacheOutbound):
503     """ IPSec/IPv4 outbound: Policy mode test case with flow cache \
504         (hash collision)"""
505     # Override class setup to restrict vector size to 16 elements.
506     # This forces using only the lower 4 bits of the hash as a key,
507     # making hash collisions easy to find.
508     @classmethod
509     def setUpConstants(cls):
510         super(SpdFlowCacheOutbound, cls).setUpConstants()
511         cls.vpp_cmdline.extend(["ipsec", "{",
512                                 "ipv4-outbound-spd-flow-cache on",
513                                 "ipv4-outbound-spd-hash-buckets 16",
514                                 "}"])
515         cls.logger.info("VPP modified cmdline is %s" % " "
516                         .join(cls.vpp_cmdline))
517
518     def test_ipsec_spd_outbound_collision(self):
519         # The flow cache operation is setup to overwrite an entry
520         # if a hash collision occurs.
521         # In this test, 2 packets are configured that result in a
522         # hash with the same lower 4 bits.
523         # After the first packet is received, there should be one
524         # active entry in the flow cache.
525         # After the second packet with the same lower 4 bit hash
526         # is received, this should overwrite the same entry.
527         # Therefore there will still be a total of one (1) entry,
528         # in the flow cache with two matching policies.
529         # crc32_supported() method is used to check cpu for crc32
530         # intrinsic support for hashing.
531         # If crc32 is not supported, we fall back to clib_xxhash()
532         self.create_interfaces(3)
533         pkt_count = 5
534         # bind SPD to all interfaces
535         self.spd_create_and_intf_add(1, self.pg_interfaces)
536         # add rules
537         policy_0 = self.spd_add_rem_policy(  # outbound, priority 10
538             1, self.pg1, self.pg2, socket.IPPROTO_UDP,
539             is_out=1, priority=10, policy_type="bypass")
540         policy_1 = self.spd_add_rem_policy(  # outbound, priority 10
541             1, self.pg2, self.pg0, socket.IPPROTO_UDP,
542             is_out=1, priority=10, policy_type="bypass")
543
544         # interfaces bound to an SPD, will by default drop inbound
545         # traffic with no matching policies. add catch-all inbound
546         # bypass rule to SPD:
547         self.spd_add_rem_policy(  # inbound, all interfaces
548             1, None, None, socket.IPPROTO_UDP, is_out=0, priority=10,
549             policy_type="bypass", all_ips=True)
550
551         # check flow cache is empty (0 active elements) before sending traffic
552         self.verify_num_outbound_flow_cache_entries(0)
553
554         # create the packet streams generating collision on last 4 bits
555         if self.crc32_supported():
556             # packet hashes to:
557             # 432c99c2
558             packets1 = self.create_stream(self.pg1, self.pg2, pkt_count, 1, 1)
559             # 31f8f3f2
560             packets2 = self.create_stream(self.pg2, self.pg0, pkt_count, 6, 6)
561         else:  # clib_xxhash
562             # ec3a258551bc0306
563             packets1 = self.create_stream(self.pg1, self.pg2, pkt_count, 2, 2)
564             # 61fee526d18d7a6
565             packets2 = self.create_stream(self.pg2, self.pg0, pkt_count, 3, 3)
566
567         # add the streams to the source interfaces
568         self.pg1.add_stream(packets1)
569         self.pg2.add_stream(packets2)
570         # enable capture on all interfaces
571         for pg in self.pg_interfaces:
572             pg.enable_capture()
573         # start the packet generator
574         self.pg_start()
575
576         # get captures from ifs - the proper pkt_count of packets was saved by
577         # create_packet_info() based on dst_if parameter
578         if_caps = []
579         for pg in [self.pg2, self.pg0]:  # we are expecting captures on pg2/pg0
580             if_caps.append(pg.get_capture())
581             for packet in if_caps[-1]:
582                 try:
583                     self.logger.debug(ppp(
584                         "SPD - Got packet:", packet))
585                 except Exception:
586                     self.logger.error(ppp(
587                         "Unexpected or invalid packet:", packet))
588                     raise
589         self.logger.debug("SPD: Num packets: %s", len(if_caps[0].res))
590         self.logger.debug("SPD: Num packets: %s", len(if_caps[1].res))
591
592         # verify captures that matched BYPASS rule
593         self.verify_capture(self.pg1, self.pg2, if_caps[0])
594         self.verify_capture(self.pg2, self.pg0, if_caps[1])
595         # verify all packets that were expected to match rules, matched
596         self.verify_policy_match(pkt_count, policy_0)
597         self.verify_policy_match(pkt_count, policy_1)
598         # we have matched 2 policies, but due to the hash collision
599         # one active entry is expected
600         self.verify_num_outbound_flow_cache_entries(1)
601
602
603 if __name__ == '__main__':
604     unittest.main(testRunner=VppTestRunner)