1
# Copyright (C) 2014,2015 VA Linux Systems Japan K.K.
2
# Copyright (C) 2014,2015 YAMAMOTO Takashi <yamamoto at valinux co jp>
5
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6
# not use this file except in compliance with the License. You may obtain
7
# a copy of the License at
9
# http://www.apache.org/licenses/LICENSE-2.0
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
# License for the specific language governing permissions and limitations
19
import neutron.plugins.ml2.drivers.openvswitch.agent.common.constants \
21
from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent.openflow.native \
22
import ovs_bridge_test_base
25
call = mock.call # short hand
28
class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase,
29
ovs_bridge_test_base.OVSDVRProcessTestMixin):
30
dvr_process_table_id = ovs_const.DVR_PROCESS
31
dvr_process_next_table_id = ovs_const.PATCH_LV_TO_TUN
34
super(OVSTunnelBridgeTest, self).setUp()
35
self.setup_bridge_mock('br-tun', self.br_tun_cls)
37
def test_setup_default_table(self):
38
patch_int_ofport = 5555
39
arp_responder_enabled = False
40
self.br.setup_default_table(patch_int_ofport=patch_int_ofport,
41
arp_responder_enabled=arp_responder_enabled)
42
(dp, ofp, ofpp) = self._get_dp()
44
call._send_msg(ofpp.OFPFlowMod(dp,
46
instructions=[ofpp.OFPInstructionGotoTable(table_id=2)],
47
match=ofpp.OFPMatch(in_port=patch_int_ofport),
48
priority=1, table_id=0)),
49
call._send_msg(ofpp.OFPFlowMod(dp,
52
match=ofpp.OFPMatch(),
53
priority=0, table_id=0)),
54
call._send_msg(ofpp.OFPFlowMod(dp,
56
instructions=[ofpp.OFPInstructionGotoTable(table_id=20)],
58
eth_dst=('00:00:00:00:00:00', '01:00:00:00:00:00')),
61
call._send_msg(ofpp.OFPFlowMod(dp,
63
instructions=[ofpp.OFPInstructionGotoTable(table_id=22)],
65
eth_dst=('01:00:00:00:00:00', '01:00:00:00:00:00')),
68
call._send_msg(ofpp.OFPFlowMod(dp,
71
match=ofpp.OFPMatch(),
72
priority=0, table_id=3)),
73
call._send_msg(ofpp.OFPFlowMod(dp,
76
match=ofpp.OFPMatch(),
77
priority=0, table_id=4)),
78
call._send_msg(ofpp.OFPFlowMod(dp,
81
match=ofpp.OFPMatch(),
82
priority=0, table_id=6)),
83
call._send_msg(ofpp.OFPFlowMod(dp,
86
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
105
dst=('tunnel_id', 0),
107
src=('tunnel_id', 0)),
108
ofpp.NXFlowSpecOutput(
114
ofpp.OFPActionOutput(patch_int_ofport, 0),
117
match=ofpp.OFPMatch(),
120
call._send_msg(ofpp.OFPFlowMod(dp,
122
instructions=[ofpp.OFPInstructionGotoTable(table_id=22)],
123
match=ofpp.OFPMatch(),
126
call._send_msg(ofpp.OFPFlowMod(dp,
129
match=ofpp.OFPMatch(),
133
self.assertEqual(expected, self.mock.mock_calls)
135
def test_setup_default_table_arp_responder_enabled(self):
136
patch_int_ofport = 5555
137
arp_responder_enabled = True
138
self.br.setup_default_table(patch_int_ofport=patch_int_ofport,
139
arp_responder_enabled=arp_responder_enabled)
140
(dp, ofp, ofpp) = self._get_dp()
142
call._send_msg(ofpp.OFPFlowMod(dp,
144
instructions=[ofpp.OFPInstructionGotoTable(table_id=2)],
145
match=ofpp.OFPMatch(in_port=patch_int_ofport),
146
priority=1, table_id=0)),
147
call._send_msg(ofpp.OFPFlowMod(dp,
150
match=ofpp.OFPMatch(),
151
priority=0, table_id=0)),
152
call._send_msg(ofpp.OFPFlowMod(dp,
154
instructions=[ofpp.OFPInstructionGotoTable(table_id=21)],
156
eth_dst='ff:ff:ff:ff:ff:ff',
157
eth_type=self.ether_types.ETH_TYPE_ARP),
160
call._send_msg(ofpp.OFPFlowMod(dp,
162
instructions=[ofpp.OFPInstructionGotoTable(table_id=20)],
164
eth_dst=('00:00:00:00:00:00', '01:00:00:00:00:00')),
167
call._send_msg(ofpp.OFPFlowMod(dp,
169
instructions=[ofpp.OFPInstructionGotoTable(table_id=22)],
171
eth_dst=('01:00:00:00:00:00', '01:00:00:00:00:00')),
174
call._send_msg(ofpp.OFPFlowMod(dp,
177
match=ofpp.OFPMatch(),
178
priority=0, table_id=3)),
179
call._send_msg(ofpp.OFPFlowMod(dp,
182
match=ofpp.OFPMatch(),
183
priority=0, table_id=4)),
184
call._send_msg(ofpp.OFPFlowMod(dp,
187
match=ofpp.OFPMatch(),
188
priority=0, table_id=6)),
189
call._send_msg(ofpp.OFPFlowMod(dp,
192
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
198
ofpp.NXFlowSpecMatch(
201
src=('vlan_vid', 0)),
202
ofpp.NXFlowSpecMatch(
211
dst=('tunnel_id', 0),
213
src=('tunnel_id', 0)),
214
ofpp.NXFlowSpecOutput(
220
ofpp.OFPActionOutput(patch_int_ofport, 0),
223
match=ofpp.OFPMatch(),
226
call._send_msg(ofpp.OFPFlowMod(dp,
228
instructions=[ofpp.OFPInstructionGotoTable(table_id=22)],
229
match=ofpp.OFPMatch(),
232
call._send_msg(ofpp.OFPFlowMod(dp,
234
instructions=[ofpp.OFPInstructionGotoTable(table_id=22)],
235
match=ofpp.OFPMatch(),
238
call._send_msg(ofpp.OFPFlowMod(dp,
241
match=ofpp.OFPMatch(),
245
self.assertEqual(expected, self.mock.mock_calls)
247
def test_provision_local_vlan(self):
248
network_type = 'vxlan'
250
segmentation_id = 777
252
self.br.provision_local_vlan(network_type=network_type, lvid=lvid,
253
segmentation_id=segmentation_id,
254
distributed=distributed)
255
(dp, ofp, ofpp) = self._get_dp()
257
call._send_msg(ofpp.OFPFlowMod(dp,
260
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
261
ofpp.OFPActionPushVlan(),
262
ofpp.OFPActionSetField(
263
vlan_vid=lvid | ofp.OFPVID_PRESENT)
265
ofpp.OFPInstructionGotoTable(table_id=10),
267
match=ofpp.OFPMatch(tunnel_id=segmentation_id),
271
self.assertEqual(expected, self.mock.mock_calls)
273
def test_reclaim_local_vlan(self):
274
network_type = 'vxlan'
275
segmentation_id = 777
276
self.br.reclaim_local_vlan(network_type=network_type,
277
segmentation_id=segmentation_id)
278
(dp, ofp, ofpp) = self._get_dp()
282
match=ofpp.OFPMatch(tunnel_id=segmentation_id)),
284
self.assertEqual(expected, self.mock.mock_calls)
286
def test_install_flood_to_tun(self):
289
ports = [11, 44, 22, 33]
290
self.br.install_flood_to_tun(vlan=vlan,
293
(dp, ofp, ofpp) = self._get_dp()
295
call._send_msg(ofpp.OFPFlowMod(dp,
298
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
299
ofpp.OFPActionPopVlan(),
300
ofpp.OFPActionSetField(tunnel_id=tun_id),
301
] + [ofpp.OFPActionOutput(p, 0) for p in ports]),
303
match=ofpp.OFPMatch(vlan_vid=vlan | ofp.OFPVID_PRESENT),
307
self.assertEqual(expected, self.mock.mock_calls)
309
def test_delete_flood_to_tun(self):
311
self.br.delete_flood_to_tun(vlan=vlan)
312
(dp, ofp, ofpp) = self._get_dp()
314
call.delete_flows(table_id=22,
315
match=ofpp.OFPMatch(vlan_vid=vlan | ofp.OFPVID_PRESENT)),
317
self.assertEqual(expected, self.mock.mock_calls)
319
def test_install_unicast_to_tun(self):
322
mac = '08:60:6e:7f:74:e7'
324
self.br.install_unicast_to_tun(vlan=vlan,
328
(dp, ofp, ofpp) = self._get_dp()
330
call._send_msg(ofpp.OFPFlowMod(dp,
333
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
334
ofpp.OFPActionPopVlan(),
335
ofpp.OFPActionSetField(tunnel_id=tun_id),
336
ofpp.OFPActionOutput(port, 0),
340
eth_dst=mac, vlan_vid=vlan | ofp.OFPVID_PRESENT),
344
self.assertEqual(expected, self.mock.mock_calls)
346
def test_delete_unicast_to_tun(self):
348
mac = '08:60:6e:7f:74:e7'
349
self.br.delete_unicast_to_tun(vlan=vlan, mac=mac)
350
(dp, ofp, ofpp) = self._get_dp()
352
call.delete_flows(table_id=20,
354
eth_dst=mac, vlan_vid=vlan | ofp.OFPVID_PRESENT)),
356
self.assertEqual(expected, self.mock.mock_calls)
358
def test_delete_unicast_to_tun_without_mac(self):
361
self.br.delete_unicast_to_tun(vlan=vlan, mac=mac)
362
(dp, ofp, ofpp) = self._get_dp()
364
call.delete_flows(table_id=20,
365
match=ofpp.OFPMatch(vlan_vid=vlan | ofp.OFPVID_PRESENT)),
367
self.assertEqual(expected, self.mock.mock_calls)
369
def test_install_arp_responder(self):
372
mac = '08:60:6e:7f:74:e7'
373
self.br.install_arp_responder(vlan=vlan, ip=ip, mac=mac)
374
(dp, ofp, ofpp) = self._get_dp()
376
call._send_msg(ofpp.OFPFlowMod(dp,
379
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
380
ofpp.OFPActionSetField(arp_op=self.arp.ARP_REPLY),
381
ofpp.NXActionRegMove(
384
src_field='arp_sha'),
385
ofpp.NXActionRegMove(
388
src_field='arp_spa'),
389
ofpp.OFPActionSetField(arp_sha=mac),
390
ofpp.OFPActionSetField(arp_spa=ip),
391
ofpp.OFPActionOutput(ofp.OFPP_IN_PORT, 0),
395
eth_type=self.ether_types.ETH_TYPE_ARP,
397
vlan_vid=vlan | ofp.OFPVID_PRESENT),
401
self.assertEqual(expected, self.mock.mock_calls)
403
def test_delete_arp_responder(self):
406
self.br.delete_arp_responder(vlan=vlan, ip=ip)
407
(dp, ofp, ofpp) = self._get_dp()
411
eth_type=self.ether_types.ETH_TYPE_ARP,
413
vlan_vid=vlan | ofp.OFPVID_PRESENT),
416
self.assertEqual(expected, self.mock.mock_calls)
418
def test_delete_arp_responder_without_ip(self):
421
self.br.delete_arp_responder(vlan=vlan, ip=ip)
422
(dp, ofp, ofpp) = self._get_dp()
426
eth_type=self.ether_types.ETH_TYPE_ARP,
427
vlan_vid=vlan | ofp.OFPVID_PRESENT),
430
self.assertEqual(expected, self.mock.mock_calls)
432
def test_setup_tunnel_port(self):
433
network_type = 'vxlan'
435
self.br.setup_tunnel_port(network_type=network_type, port=port)
436
(dp, ofp, ofpp) = self._get_dp()
438
call._send_msg(ofpp.OFPFlowMod(dp,
441
ofpp.OFPInstructionGotoTable(table_id=4),
443
match=ofpp.OFPMatch(in_port=port),
447
self.assertEqual(expected, self.mock.mock_calls)
449
def test_cleanup_tunnel_port(self):
451
self.br.cleanup_tunnel_port(port=port)
452
(dp, ofp, ofpp) = self._get_dp()
454
call.delete_flows(in_port=port),
456
self.assertEqual(expected, self.mock.mock_calls)
458
def test_add_dvr_mac_tun(self):
459
mac = '00:02:b3:13:fe:3d'
461
self.br.add_dvr_mac_tun(mac=mac, port=port)
462
(dp, ofp, ofpp) = self._get_dp()
464
call._send_msg(ofpp.OFPFlowMod(dp,
467
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
468
ofpp.OFPActionOutput(port, 0),
471
match=ofpp.OFPMatch(eth_src=mac),
475
self.assertEqual(expected, self.mock.mock_calls)
477
def test_remove_dvr_mac_tun(self):
478
mac = '00:02:b3:13:fe:3d'
479
self.br.remove_dvr_mac_tun(mac=mac)
480
(dp, ofp, ofpp) = self._get_dp()
482
call.delete_flows(eth_src=mac, table_id=9),
484
self.assertEqual(expected, self.mock.mock_calls)