Skip to content

Commit 54d82ff

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "[ML2/OVS] Maintain learning OF rules for GARP/ND in br-tun" into stable/2025.1
2 parents 0eca108 + 77369fa commit 54d82ff

File tree

2 files changed

+136
-110
lines changed
  • neutron
    • plugins/ml2/drivers/openvswitch/agent/openflow/native
    • tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native

2 files changed

+136
-110
lines changed

neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_tun.py

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
# License for the specific language governing permissions and limitations
1616
# under the License.
1717

18+
from neutron_lib import constants as lib_constants
1819
from neutron_lib.plugins.ml2 import ovs_constants as constants
1920
from os_ken.lib.packet import ether_types
21+
from os_ken.lib.packet import icmpv6
22+
from os_ken.lib.packet import in_proto
2023

2124
from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \
2225
import br_dvr_process
@@ -33,6 +36,62 @@ class OVSTunnelBridge(ovs_bridge.OVSAgentBridge,
3336
dvr_process_next_table_id = constants.PATCH_LV_TO_TUN
3437
of_tables = constants.TUN_BR_ALL_TABLES
3538

39+
def _setup_learn_flows(self, ofpp, patch_int_ofport):
40+
flow_specs = [
41+
ofpp.NXFlowSpecMatch(src=('vlan_tci', 0),
42+
dst=('vlan_tci', 0),
43+
n_bits=12),
44+
ofpp.NXFlowSpecMatch(src=('eth_src', 0),
45+
dst=('eth_dst', 0),
46+
n_bits=48),
47+
ofpp.NXFlowSpecLoad(src=0,
48+
dst=('vlan_tci', 0),
49+
n_bits=16),
50+
ofpp.NXFlowSpecLoad(src=('tunnel_id', 0),
51+
dst=('tunnel_id', 0),
52+
n_bits=64),
53+
ofpp.NXFlowSpecOutput(src=('in_port', 0),
54+
dst='',
55+
n_bits=32),
56+
]
57+
actions = [
58+
ofpp.NXActionLearn(table_id=constants.UCAST_TO_TUN,
59+
cookie=self.default_cookie,
60+
priority=1,
61+
hard_timeout=300,
62+
specs=flow_specs),
63+
ofpp.OFPActionOutput(patch_int_ofport, 0),
64+
]
65+
66+
arp_match = ofpp.OFPMatch(
67+
eth_type=ether_types.ETH_TYPE_ARP,
68+
arp_tha=lib_constants.BROADCAST_MAC
69+
)
70+
ipv6_ra_match = ofpp.OFPMatch(
71+
eth_type=ether_types.ETH_TYPE_IPV6,
72+
ip_proto=in_proto.IPPROTO_ICMPV6,
73+
icmpv6_type=icmpv6.ND_ROUTER_ADVERT) # icmp_type=134
74+
ipv6_na_match = ofpp.OFPMatch(
75+
eth_type=ether_types.ETH_TYPE_IPV6,
76+
ip_proto=in_proto.IPPROTO_ICMPV6,
77+
icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT) # icmp_type=136
78+
79+
self.install_apply_actions(table_id=constants.LEARN_FROM_TUN,
80+
priority=2,
81+
match=arp_match,
82+
actions=actions)
83+
self.install_apply_actions(table_id=constants.LEARN_FROM_TUN,
84+
priority=2,
85+
match=ipv6_ra_match,
86+
actions=actions)
87+
self.install_apply_actions(table_id=constants.LEARN_FROM_TUN,
88+
priority=2,
89+
match=ipv6_na_match,
90+
actions=actions)
91+
self.install_apply_actions(table_id=constants.LEARN_FROM_TUN,
92+
priority=1,
93+
actions=actions)
94+
3695
def setup_default_table(
3796
self, patch_int_ofport, arp_responder_enabled, dvr_enabled):
3897
(dp, ofp, ofpp) = self._get_dp()
@@ -81,34 +140,7 @@ def setup_default_table(
81140
# dynamically set-up flows in UCAST_TO_TUN corresponding to remote mac
82141
# addresses (assumes that lvid has already been set by a previous flow)
83142
# Once remote mac addresses are learnt, output packet to patch_int
84-
flow_specs = [
85-
ofpp.NXFlowSpecMatch(src=('vlan_tci', 0),
86-
dst=('vlan_tci', 0),
87-
n_bits=12),
88-
ofpp.NXFlowSpecMatch(src=('eth_src', 0),
89-
dst=('eth_dst', 0),
90-
n_bits=48),
91-
ofpp.NXFlowSpecLoad(src=0,
92-
dst=('vlan_tci', 0),
93-
n_bits=16),
94-
ofpp.NXFlowSpecLoad(src=('tunnel_id', 0),
95-
dst=('tunnel_id', 0),
96-
n_bits=64),
97-
ofpp.NXFlowSpecOutput(src=('in_port', 0),
98-
dst='',
99-
n_bits=32),
100-
]
101-
actions = [
102-
ofpp.NXActionLearn(table_id=constants.UCAST_TO_TUN,
103-
cookie=self.default_cookie,
104-
priority=1,
105-
hard_timeout=300,
106-
specs=flow_specs),
107-
ofpp.OFPActionOutput(patch_int_ofport, 0),
108-
]
109-
self.install_apply_actions(table_id=constants.LEARN_FROM_TUN,
110-
priority=1,
111-
actions=actions)
143+
self._setup_learn_flows(ofpp, patch_int_ofport)
112144

113145
# Egress unicast will be handled in table UCAST_TO_TUN, where remote
114146
# mac addresses will be learned. For now, just add a default flow that

neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_tun.py

Lines changed: 76 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from unittest import mock
1818

19+
from neutron_lib import constants as lib_constants
1920
from neutron_lib.plugins.ml2 import ovs_constants as ovs_const
2021

2122
from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent.openflow.native \
@@ -48,6 +49,75 @@ def setUp(self):
4849
self.setup_bridge_mock('br-tun', self.br_tun_cls)
4950
self.stamp = self.br.default_cookie
5051

52+
def _get_learn_flows(self, ofpp, patch_int_ofport):
53+
(dp, ofp, ofpp) = self._get_dp()
54+
# flows_data is list of tuples (priority, match)
55+
flows_data = [
56+
(2, ofpp.OFPMatch(
57+
eth_type=self.ether_types.ETH_TYPE_ARP,
58+
arp_tha=lib_constants.BROADCAST_MAC
59+
)),
60+
(2, ofpp.OFPMatch(
61+
eth_type=self.ether_types.ETH_TYPE_IPV6,
62+
ip_proto=self.in_proto.IPPROTO_ICMPV6,
63+
icmpv6_type=self.icmpv6.ND_ROUTER_ADVERT
64+
)),
65+
(2, ofpp.OFPMatch(
66+
eth_type=self.ether_types.ETH_TYPE_IPV6,
67+
ip_proto=self.in_proto.IPPROTO_ICMPV6,
68+
icmpv6_type=self.icmpv6.ND_NEIGHBOR_ADVERT
69+
)),
70+
(1, ofpp.OFPMatch())
71+
]
72+
learn_flows = []
73+
for priority, match in flows_data:
74+
learn_flows.append(
75+
call._send_msg(
76+
ofpp.OFPFlowMod(
77+
dp,
78+
cookie=self.stamp,
79+
instructions=[
80+
ofpp.OFPInstructionActions(
81+
ofp.OFPIT_APPLY_ACTIONS, [
82+
ofpp.NXActionLearn(
83+
cookie=self.stamp,
84+
hard_timeout=300,
85+
priority=1,
86+
specs=[
87+
ofpp.NXFlowSpecMatch(
88+
dst=('vlan_tci', 0),
89+
n_bits=12,
90+
src=('vlan_tci', 0)),
91+
ofpp.NXFlowSpecMatch(
92+
dst=('eth_dst', 0),
93+
n_bits=48,
94+
src=('eth_src', 0)),
95+
ofpp.NXFlowSpecLoad(
96+
dst=('vlan_tci', 0),
97+
n_bits=16,
98+
src=0),
99+
ofpp.NXFlowSpecLoad(
100+
dst=('tunnel_id', 0),
101+
n_bits=64,
102+
src=('tunnel_id', 0)),
103+
ofpp.NXFlowSpecOutput(
104+
dst='',
105+
n_bits=32,
106+
src=('in_port', 0)),
107+
],
108+
table_id=20),
109+
ofpp.OFPActionOutput(patch_int_ofport, 0),
110+
]
111+
),
112+
],
113+
match=match,
114+
priority=priority,
115+
table_id=10),
116+
active_bundle=None
117+
)
118+
)
119+
return learn_flows
120+
51121
def test_setup_default_table(self):
52122
patch_int_ofport = 5555
53123
arp_responder_enabled = False
@@ -110,47 +180,9 @@ def test_setup_default_table(self):
110180
instructions=[],
111181
match=ofpp.OFPMatch(),
112182
priority=0, table_id=6),
113-
active_bundle=None),
114-
call._send_msg(
115-
ofpp.OFPFlowMod(
116-
dp,
117-
cookie=self.stamp,
118-
instructions=[
119-
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
120-
ofpp.NXActionLearn(
121-
cookie=self.stamp,
122-
hard_timeout=300,
123-
priority=1,
124-
specs=[
125-
ofpp.NXFlowSpecMatch(
126-
dst=('vlan_tci', 0),
127-
n_bits=12,
128-
src=('vlan_tci', 0)),
129-
ofpp.NXFlowSpecMatch(
130-
dst=('eth_dst', 0),
131-
n_bits=48,
132-
src=('eth_src', 0)),
133-
ofpp.NXFlowSpecLoad(
134-
dst=('vlan_tci', 0),
135-
n_bits=16,
136-
src=0),
137-
ofpp.NXFlowSpecLoad(
138-
dst=('tunnel_id', 0),
139-
n_bits=64,
140-
src=('tunnel_id', 0)),
141-
ofpp.NXFlowSpecOutput(
142-
dst='',
143-
n_bits=32,
144-
src=('in_port', 0)),
145-
],
146-
table_id=20),
147-
ofpp.OFPActionOutput(patch_int_ofport, 0),
148-
]),
149-
],
150-
match=ofpp.OFPMatch(),
151-
priority=1,
152-
table_id=10),
153-
active_bundle=None),
183+
active_bundle=None)]
184+
expected += self._get_learn_flows(ofpp, patch_int_ofport)
185+
expected += [
154186
call._send_msg(
155187
ofpp.OFPFlowMod(dp,
156188
cookie=self.stamp,
@@ -243,47 +275,9 @@ def test_setup_default_table_arp_responder_enabled(self):
243275
instructions=[],
244276
match=ofpp.OFPMatch(),
245277
priority=0, table_id=6),
246-
active_bundle=None),
247-
call._send_msg(
248-
ofpp.OFPFlowMod(
249-
dp,
250-
cookie=self.stamp,
251-
instructions=[
252-
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
253-
ofpp.NXActionLearn(
254-
cookie=self.stamp,
255-
hard_timeout=300,
256-
priority=1,
257-
specs=[
258-
ofpp.NXFlowSpecMatch(
259-
dst=('vlan_tci', 0),
260-
n_bits=12,
261-
src=('vlan_tci', 0)),
262-
ofpp.NXFlowSpecMatch(
263-
dst=('eth_dst', 0),
264-
n_bits=48,
265-
src=('eth_src', 0)),
266-
ofpp.NXFlowSpecLoad(
267-
dst=('vlan_tci', 0),
268-
n_bits=16,
269-
src=0),
270-
ofpp.NXFlowSpecLoad(
271-
dst=('tunnel_id', 0),
272-
n_bits=64,
273-
src=('tunnel_id', 0)),
274-
ofpp.NXFlowSpecOutput(
275-
dst='',
276-
n_bits=32,
277-
src=('in_port', 0)),
278-
],
279-
table_id=20),
280-
ofpp.OFPActionOutput(patch_int_ofport, 0),
281-
]),
282-
],
283-
match=ofpp.OFPMatch(),
284-
priority=1,
285-
table_id=10),
286-
active_bundle=None),
278+
active_bundle=None)]
279+
expected += self._get_learn_flows(ofpp, patch_int_ofport)
280+
expected += [
287281
call._send_msg(
288282
ofpp.OFPFlowMod(dp,
289283
cookie=self.stamp,

0 commit comments

Comments
 (0)