blob: 9d44fc1a21cf31002d466b9a5ff72676057ac2fc [file] [log] [blame]
Brian Russell6e6920d2021-02-17 15:54:52 +00001#!/usr/bin/env python3
2# Copyright (c) 2021 Graphiant, Inc.
3
4import unittest
5import scapy.compat
6from scapy.layers.inet import IP, UDP
7from scapy.layers.l2 import Ether
8from scapy.packet import Raw
9from framework import VppTestCase, VppTestRunner
10from vpp_papi import VppEnum
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020011from vpp_policer import VppPolicer, PolicerAction, Dir
Brian Russell6e6920d2021-02-17 15:54:52 +000012
13NUM_PKTS = 67
14
15
16class TestPolicerInput(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020017 """Policer on an interface"""
18
Klement Sekera8d815022021-03-15 16:58:10 +010019 vpp_worker_count = 2
Brian Russell6e6920d2021-02-17 15:54:52 +000020
21 def setUp(self):
22 super(TestPolicerInput, self).setUp()
23
24 self.create_pg_interfaces(range(2))
25 for i in self.pg_interfaces:
26 i.admin_up()
27 i.config_ip4()
28 i.resolve_arp()
29
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020030 self.pkt = (
31 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
32 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
33 / UDP(sport=1234, dport=1234)
34 / Raw(b"\xa5" * 100)
35 )
Brian Russell6e6920d2021-02-17 15:54:52 +000036
37 def tearDown(self):
38 for i in self.pg_interfaces:
39 i.unconfig_ip4()
40 i.admin_down()
41 super(TestPolicerInput, self).tearDown()
42
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020043 def policer_interface_test(self, dir: Dir):
Brian Russell26bcbc12021-02-18 11:02:29 +000044 pkts = self.pkt * NUM_PKTS
45
Brian Russell6e6920d2021-02-17 15:54:52 +000046 action_tx = PolicerAction(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020047 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
48 )
49 policer = VppPolicer(
50 self,
51 "pol1",
52 80,
53 0,
54 1000,
55 0,
56 conform_action=action_tx,
57 exceed_action=action_tx,
58 violate_action=action_tx,
59 )
Brian Russell6e6920d2021-02-17 15:54:52 +000060 policer.add_vpp_config()
61
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020062 sw_if_index = self.pg0.sw_if_index if dir == Dir.RX else self.pg1.sw_if_index
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020063
Brian Russell6e6920d2021-02-17 15:54:52 +000064 # Start policing on pg0
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020065 policer.apply_vpp_config(sw_if_index, dir, True)
Brian Russell6e6920d2021-02-17 15:54:52 +000066
Brian Russell26bcbc12021-02-18 11:02:29 +000067 rx = self.send_and_expect(self.pg0, pkts, self.pg1, worker=0)
Brian Russell6e6920d2021-02-17 15:54:52 +000068 stats = policer.get_stats()
69
70 # Single rate, 2 colour policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020071 self.assertGreater(stats["conform_packets"], 0)
72 self.assertEqual(stats["exceed_packets"], 0)
73 self.assertGreater(stats["violate_packets"], 0)
Brian Russell6e6920d2021-02-17 15:54:52 +000074
75 # Stop policing on pg0
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020076 policer.apply_vpp_config(sw_if_index, dir, False)
Brian Russell6e6920d2021-02-17 15:54:52 +000077
Brian Russell26bcbc12021-02-18 11:02:29 +000078 rx = self.send_and_expect(self.pg0, pkts, self.pg1, worker=0)
79
Brian Russell6e6920d2021-02-17 15:54:52 +000080 statsnew = policer.get_stats()
81
82 # No new packets counted
83 self.assertEqual(stats, statsnew)
84
85 policer.remove_vpp_config()
86
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020087 def test_policer_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020088 """Input Policing"""
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020089 self.policer_interface_test(Dir.RX)
90
91 def test_policer_output(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020092 """Output Policing"""
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +020093 self.policer_interface_test(Dir.TX)
94
95 def policer_handoff_test(self, dir: Dir):
Brian Russell26bcbc12021-02-18 11:02:29 +000096 pkts = self.pkt * NUM_PKTS
97
98 action_tx = PolicerAction(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020099 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
100 )
101 policer = VppPolicer(
102 self,
103 "pol2",
104 80,
105 0,
106 1000,
107 0,
108 conform_action=action_tx,
109 exceed_action=action_tx,
110 violate_action=action_tx,
111 )
Brian Russell26bcbc12021-02-18 11:02:29 +0000112 policer.add_vpp_config()
113
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200114 sw_if_index = self.pg0.sw_if_index if dir == Dir.RX else self.pg1.sw_if_index
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200115
Brian Russell26bcbc12021-02-18 11:02:29 +0000116 # Bind the policer to worker 1
117 policer.bind_vpp_config(1, True)
118
119 # Start policing on pg0
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200120 policer.apply_vpp_config(sw_if_index, dir, True)
Brian Russell26bcbc12021-02-18 11:02:29 +0000121
122 for worker in [0, 1]:
123 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
124 self.logger.debug(self.vapi.cli("show trace max 100"))
125
126 stats = policer.get_stats()
127 stats0 = policer.get_stats(worker=0)
128 stats1 = policer.get_stats(worker=1)
129
130 # Worker 1, should have done all the policing
131 self.assertEqual(stats, stats1)
132
133 # Worker 0, should have handed everything off
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200134 self.assertEqual(stats0["conform_packets"], 0)
135 self.assertEqual(stats0["exceed_packets"], 0)
136 self.assertEqual(stats0["violate_packets"], 0)
Brian Russell26bcbc12021-02-18 11:02:29 +0000137
138 # Unbind the policer from worker 1 and repeat
139 policer.bind_vpp_config(1, False)
140 for worker in [0, 1]:
141 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
142 self.logger.debug(self.vapi.cli("show trace max 100"))
143
144 # The policer should auto-bind to worker 0 when packets arrive
145 stats = policer.get_stats()
146
147 # The 2 workers should now have policed the same amount
148 stats = policer.get_stats()
149 stats0 = policer.get_stats(worker=0)
150 stats1 = policer.get_stats(worker=1)
151
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200152 self.assertGreater(stats0["conform_packets"], 0)
153 self.assertEqual(stats0["exceed_packets"], 0)
154 self.assertGreater(stats0["violate_packets"], 0)
Brian Russell26bcbc12021-02-18 11:02:29 +0000155
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200156 self.assertGreater(stats1["conform_packets"], 0)
157 self.assertEqual(stats1["exceed_packets"], 0)
158 self.assertGreater(stats1["violate_packets"], 0)
Brian Russell26bcbc12021-02-18 11:02:29 +0000159
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200160 self.assertEqual(
161 stats0["conform_packets"] + stats1["conform_packets"],
162 stats["conform_packets"],
163 )
Brian Russell26bcbc12021-02-18 11:02:29 +0000164
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200165 self.assertEqual(
166 stats0["violate_packets"] + stats1["violate_packets"],
167 stats["violate_packets"],
168 )
Brian Russell26bcbc12021-02-18 11:02:29 +0000169
170 # Stop policing on pg0
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200171 policer.apply_vpp_config(sw_if_index, dir, False)
Brian Russell26bcbc12021-02-18 11:02:29 +0000172
173 policer.remove_vpp_config()
Brian Russell6e6920d2021-02-17 15:54:52 +0000174
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200175 def test_policer_handoff_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200176 """Worker thread handoff policer input"""
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200177 self.policer_handoff_test(Dir.RX)
178
179 def test_policer_handoff_output(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200180 """Worker thread handoff policer output"""
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200181 self.policer_handoff_test(Dir.TX)
182
183
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200184if __name__ == "__main__":
Brian Russell6e6920d2021-02-17 15:54:52 +0000185 unittest.main(testRunner=VppTestRunner)