Add table for pps limitaion

Table 59 will be used for pps limitation, the pipeline change is:
all original flows with ``goto table 60`` will be changed to
``goto table 59``, while table 59 has a default rule is goto
table 60. Then we can add pps flows to table 59 for all ports.

Basic limit pipeline is:
Ingress: packets get into br-int table 0, before send to table 60,
in table 59, check the destanation MAC and local_vlan ID, if the
dest is resident in this host, do the meter pps action and send
to table 60.
Egress: match src MAC and in_port, before send to table 60,
in table 59, do the meter pps action and send to table 60.

Why table 59? Because for ovs-agent flow structure, all packets
will be send to table 60 to do next actions such as security group.
Between table 0 and table 60, there are tables for ARP poison/spoofing
prevention rules and MAC spoof filtering. We want similar security
checks to take effect first, so it can drop packets before filling
our limit queues (pps limitation based on data forwarding queue).
And we do not want packets go through the long march of security group
flows, in case of performance side effect when there are large amount
of packets try to send, so limit it before goto security group flows.

Partially-Implements: bp/packet-rate-limit
Related-Bug: #1938966
Related-Bug: #1912460
Change-Id: I943f610c3b6bcf05e2e752ca3b57981f523f88a8
This commit is contained in:
LIU Yulong 2021-08-06 14:11:00 +08:00
parent f324ddf769
commit 053a9d24ec
5 changed files with 39 additions and 22 deletions

View File

@ -208,9 +208,11 @@ the second security group. Ports have following attributes:
Port 3
- patch bridge port (e.g. patch-tun) in OVS bridge
|table_0| contains a low priority rule to continue packets processing in
|table_60| aka TRANSIENT table. |table_0| is left for use to other
features that take precedence over firewall, e.g. DVR. The only requirement is
|table_0| - |table_59| contain some low priority rules to continue packets
processing in |table_60| aka TRANSIENT table. |table_0| - |table_59| is
left for use to other features that take precedence over firewall, e.g.
DVR, ARP poison/spoofing prevention, MAC spoof filtering and packet rate
limitation etc. The only requirement is
that after such a feature is done with its processing, it needs to pass packets
for processing to the TRANSIENT table. This TRANSIENT table distinguishes the
ingress traffic from the egress traffic and loads into ``register 5`` a value
@ -592,6 +594,7 @@ switched to the OVS driver.
not work if one tries to replace openvswitch firewall with iptables.
.. |table_0| replace:: ``table 0`` (LOCAL_SWITCHING)
.. |table_59| replace:: ``table 59`` (PACKET_RATE_LIMIT)
.. |table_60| replace:: ``table 60`` (TRANSIENT)
.. |table_71| replace:: ``table 71`` (BASE_EGRESS)
.. |table_72| replace:: ``table 72`` (RULES_EGRESS)

View File

@ -60,6 +60,8 @@ MAC_SPOOF_TABLE = 25
LOCAL_EGRESS_TABLE = 30
LOCAL_IP_TABLE = 31
# packet rate limit table
PACKET_RATE_LIMIT = 59
# Table to decide whether further filtering is needed
TRANSIENT_TABLE = 60
LOCAL_MAC_DIRECT = 61
@ -100,6 +102,7 @@ INT_BR_ALL_TABLES = (
LOCAL_MAC_DIRECT,
LOCAL_EGRESS_TABLE,
LOCAL_IP_TABLE,
PACKET_RATE_LIMIT,
TRANSIENT_TABLE,
TRANSIENT_EGRESS_TABLE,
BASE_EGRESS_TABLE,

View File

@ -53,7 +53,7 @@ class OVSDVRInterfaceMixin(object):
]
instructions = [
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions),
ofpp.OFPInstructionGotoTable(table_id=constants.TRANSIENT_TABLE)]
ofpp.OFPInstructionGotoTable(table_id=constants.PACKET_RATE_LIMIT)]
self.install_instructions(table_id=constants.LOCAL_SWITCHING,
priority=99,

View File

@ -53,7 +53,9 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge,
enable_dhcpv6=False):
(_dp, ofp, ofpp) = self._get_dp()
self.setup_canary_table()
self.install_goto(dest_table_id=constants.TRANSIENT_TABLE)
self.install_goto(dest_table_id=constants.PACKET_RATE_LIMIT)
self.install_goto(dest_table_id=constants.TRANSIENT_TABLE,
table_id=constants.PACKET_RATE_LIMIT)
self.install_normal(table_id=constants.TRANSIENT_TABLE, priority=3)
self.init_dhcp(enable_openflow_dhcp=enable_openflow_dhcp,
enable_dhcpv6=enable_dhcpv6)
@ -69,9 +71,9 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge,
priority=3)
# Local IP defaults
self.install_goto(dest_table_id=constants.TRANSIENT_TABLE,
self.install_goto(dest_table_id=constants.PACKET_RATE_LIMIT,
table_id=constants.LOCAL_EGRESS_TABLE)
self.install_goto(dest_table_id=constants.TRANSIENT_TABLE,
self.install_goto(dest_table_id=constants.PACKET_RATE_LIMIT,
table_id=constants.LOCAL_IP_TABLE)
def init_dhcp(self, enable_openflow_dhcp=False, enable_dhcpv6=False):
@ -184,7 +186,7 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge,
]
instructions = [
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions),
ofpp.OFPInstructionGotoTable(table_id=constants.TRANSIENT_TABLE),
ofpp.OFPInstructionGotoTable(table_id=constants.PACKET_RATE_LIMIT),
]
self.install_instructions(
instructions=instructions,
@ -265,7 +267,7 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge,
]
instructions = [
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions),
ofpp.OFPInstructionGotoTable(table_id=constants.TRANSIENT_TABLE),
ofpp.OFPInstructionGotoTable(table_id=constants.PACKET_RATE_LIMIT),
]
self.install_instructions(table_id=table_id,
priority=20,
@ -366,7 +368,7 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge,
ip_proto=in_proto.IPPROTO_ICMPV6,
icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT,
ipv6_nd_target=masked_ip, in_port=port,
dest_table_id=constants.TRANSIENT_TABLE)
dest_table_id=constants.PACKET_RATE_LIMIT)
# Now that the rules are ready, direct icmpv6 neighbor advertisement
# traffic from the port into the anti-spoof table.
@ -522,7 +524,7 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge,
def install_garp_blocker_exception(self, vlan, ip, except_ip,
table_id=constants.LOCAL_SWITCHING):
match = self._garp_blocker_exception_match(vlan, ip, except_ip)
self.install_goto(dest_table_id=constants.TRANSIENT_TABLE,
self.install_goto(dest_table_id=constants.PACKET_RATE_LIMIT,
table_id=table_id,
priority=11,
match=match)

View File

@ -47,12 +47,21 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
call._send_msg(ofpp.OFPFlowMod(dp,
cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(),
priority=0,
table_id=0),
active_bundle=None),
call._send_msg(ofpp.OFPFlowMod(dp,
cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(table_id=60),
],
match=ofpp.OFPMatch(),
priority=0,
table_id=59),
active_bundle=None),
call._send_msg(ofpp.OFPFlowMod(dp,
cookie=self.stamp,
instructions=[
@ -130,7 +139,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
call._send_msg(ofpp.OFPFlowMod(
dp, cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(),
priority=0,
@ -139,7 +148,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
call._send_msg(ofpp.OFPFlowMod(
dp, cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(),
priority=0,
@ -163,7 +172,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
ofpp.OFPActionSetField(
vlan_vid=lvid | ofp.OFPVID_PRESENT),
]),
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(
in_port=port,
@ -190,7 +199,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
ofpp.OFPActionSetField(
vlan_vid=lvid | ofp.OFPVID_PRESENT),
]),
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(
in_port=port,
@ -246,7 +255,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
ofpp.OFPActionSetField(eth_src=gateway_mac),
]),
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(
eth_dst=dst_mac,
@ -316,7 +325,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
ofpp.OFPActionSetField(eth_src=gateway_mac),
]),
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(
eth_dst=dst_mac,
@ -359,7 +368,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
ofpp.OFPActionSetField(eth_src=gateway_mac),
]),
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(
eth_dst=dst_mac,
@ -502,7 +511,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
call._send_msg(ofpp.OFPFlowMod(dp,
cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(
eth_type=self.ether_types.ETH_TYPE_IPV6,
@ -517,7 +526,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
call._send_msg(ofpp.OFPFlowMod(dp,
cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(table_id=60),
ofpp.OFPInstructionGotoTable(table_id=59),
],
match=ofpp.OFPMatch(
eth_type=self.ether_types.ETH_TYPE_IPV6,
@ -768,7 +777,7 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
expected = [
call._send_msg(ofpp.OFPFlowMod(dp, cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(table_id=60)],
ofpp.OFPInstructionGotoTable(table_id=59)],
match=ofpp.OFPMatch(
vlan_vid=vlan | ofp.OFPVID_PRESENT,
eth_type=self.ether_types.ETH_TYPE_ARP,