2 * Copyright (c) 2016 NEC Corporation and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.services;
10 import java.util.ArrayList;
11 import java.util.concurrent.ConcurrentHashMap;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.List;
18 import org.apache.commons.lang3.tuple.ImmutablePair;
19 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
20 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
21 import org.opendaylight.netvirt.openstack.netvirt.api.NodeCacheManager;
22 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
23 import org.opendaylight.netvirt.openstack.netvirt.api.TenantNetworkManager;
24 import org.opendaylight.netvirt.openstack.netvirt.api.VlanResponderProvider;
25 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
26 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
27 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
28 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
29 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
30 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
31 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
32 import org.opendaylight.netvirt.utils.mdsal.openflow.InstructionUtils;
33 import org.opendaylight.netvirt.utils.mdsal.openflow.MatchUtils;
34 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
58 import org.osgi.framework.BundleContext;
59 import org.osgi.framework.ServiceReference;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
63 public class VlanResponderService extends AbstractServiceInstance implements VlanResponderProvider, ConfigInterface {
64 private static final Logger LOG = LoggerFactory.getLogger(VlanResponderService.class);
65 private static final int PRIORITY_2 = 2;
66 private static final int PRIORITY_4 = 4;
67 private static final int PRIORITY_5 = 5;
69 private volatile ConfigurationService configurationService;
70 private volatile NodeCacheManager nodeCacheManager;
71 private volatile TenantNetworkManager tenantNetworkManager;
72 private volatile Southbound southbound;
73 private volatile INeutronNetworkCRUD neutronNetworkCache;
74 private volatile Map<String, ArrayList<ImmutablePair<String, Long>>> segmentationOfPortMap =
75 new ConcurrentHashMap<String, ArrayList<ImmutablePair<String, Long>>>();
77 public VlanResponderService() {
78 super(Service.OUTBOUND_NAT);
81 public VlanResponderService(Service service) {
86 * Creates provider network flows for internal bridge.
88 * @param dpIdInt dp Id
89 * @param segmentationId segmentation id
90 * @param patchIntPort patch port of internal bridge
91 * @param ofPort of port value
92 * @param macAddress mac address
93 * @param vlanProviderCache Initial VLAN cache with processing cache
94 * @param write - flag to indicate the operation
97 public void programProviderNetworkRulesInternal(Long dpIdInt, String segmentationId, Long ofPort, Long patchIntPort,
98 String macAddress, Map<String, Set<String>> vlanProviderCache, boolean write) {
100 programProviderBroadAndMultiCastOfRouter(dpIdInt, segmentationId, ofPort, patchIntPort, macAddress, write);
101 programProviderUnicastFlowOfRouters(dpIdInt, segmentationId, ofPort, patchIntPort, macAddress, write);
102 programProviderUnicastFlowOfExternal(dpIdInt, segmentationId, ofPort, patchIntPort, macAddress, write);
103 programProviderBroadAndMultiCastOfExternal(dpIdInt, segmentationId, ofPort, patchIntPort, macAddress, write);
104 programProviderUnicastFlowFromExternal(dpIdInt, segmentationId, ofPort, patchIntPort, macAddress, vlanProviderCache, write);
108 * Creates provider network flows for external bridge.
110 * @param dpIdExt dp id
111 * @param segmentationId segmentation id
112 * @param patchExtPort patch port of external bridge
113 * @param macAddress mac address
114 * @param vlanProviderCache Initial VLAN cache with processing cache
115 * @param write - flag indicate the operation
118 public void programProviderNetworkRulesExternal(Long dpIdExt, String segmentationId, Long patchExtPort,
119 String macAddress, Map<String, Set<String>> vlanProviderCache, boolean write) {
121 programProviderNetworkForExternal(dpIdExt, segmentationId, patchExtPort, macAddress, vlanProviderCache, write);
122 programProviderNetworkDrop(dpIdExt, patchExtPort, vlanProviderCache, write);
127 * Write or remove the flows for forward the BC/MC packets of router to patch port and
128 * the router ports connected to same external network.
129 * Sample flow: table=100, priority=5,in_port=2,dl_src=fa:16:3e:ff:9c:57,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00
130 * actions=output:3,push_vlan:0x8100,set_field:4196->vlan_vid,output:1
132 private void programProviderBroadAndMultiCastOfRouter(Long dpidLong, String segmentationId, Long ofPort, Long patchPort,
133 String macAddress, boolean write) {
135 String nodeName = OPENFLOW + dpidLong;
136 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
137 FlowBuilder flowBuilder = new FlowBuilder();
138 // Create the OF Match using MatchBuilder
139 MatchBuilder matchBuilder = new MatchBuilder();
141 MatchUtils.createInPortMatch(matchBuilder, dpidLong, ofPort);
142 matchBuilder = MatchUtils.createEthSrcDestMatch(matchBuilder, new MacAddress(macAddress),
143 new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00"));
144 flowBuilder.setMatch(matchBuilder.build());
145 // Add Flow Attributes
146 String flowName = "ProviderNetwork_BC_Router_" + dpidLong + "_" + ofPort;
147 final FlowId flowId = new FlowId(flowName);
148 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
149 .setPriority(PRIORITY_5).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
150 ArrayList<ImmutablePair<String, Long>> macAddrOfPortPairList = segmentationOfPortMap.get(segmentationId);
151 if (macAddrOfPortPairList == null) {
152 macAddrOfPortPairList = new ArrayList<ImmutablePair<String, Long>>();
153 segmentationOfPortMap.put(segmentationId, macAddrOfPortPairList);
156 ImmutablePair<String, Long> ofPortMacAddressPair = new ImmutablePair<>(macAddress, ofPort);
157 if (macAddrOfPortPairList.contains(ofPortMacAddressPair)) {
160 List<Instruction> outputInstructions = new ArrayList<Instruction>();
161 int instructionIndex = 0;
162 for (ImmutablePair<String, Long> macAddressOfPortPair : macAddrOfPortPairList) {
163 InstructionUtils.createOutputPortInstruction(instructionIndex, dpidLong, macAddressOfPortPair.getRight(),
167 // Set the Output Port/Iface
168 Instruction outputPortInstruction = InstructionUtils.createVlanOutputPortInstructions(new InstructionBuilder(),
169 dpidLong, patchPort, outputInstructions, new VlanId(Integer.valueOf(segmentationId)))
170 .setOrder(0).setKey(new InstructionKey(0)).build();
171 // Add InstructionsBuilder to FlowBuilder
172 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
173 writeFlow(flowBuilder, nodeBuilder);
174 macAddrOfPortPairList.add(ofPortMacAddressPair);
176 removeFlow(flowBuilder, nodeBuilder);
177 Iterator<ImmutablePair<String, Long>> iterator = macAddrOfPortPairList.iterator();
178 while (iterator.hasNext()) {
179 ImmutablePair<String, Long> macAddressOfPortPair = iterator.next();
180 if (macAddress.equals(macAddressOfPortPair.getLeft())) {
186 programExistingProviderBroadAndMultiCastOfRouter(dpidLong, segmentationId, ofPort, patchPort, macAddress, write);
187 } catch (Exception e) {
188 LOG.error("Error while writing/removing broadcast flows. dpidLong = {}, patchPort={}, write = {}."
189 + " Caused due to, {}", dpidLong, patchPort, write, e.getMessage());
194 * Write or remove the existing flows of forward the BC/MC packets of router to patch port and
195 * the router ports connected to same external network.
196 * Sample flow: table=100, priority=5,in_port=2,dl_src=fa:16:3e:ff:9c:57,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00
197 * actions=output:3,push_vlan:0x8100,set_field:4196->vlan_vid,output:1
199 private void programExistingProviderBroadAndMultiCastOfRouter(Long dpidLong, String segmentationId, Long currentOfPort, Long patchPort,
200 String macAddress, boolean write) {
202 String nodeName = OPENFLOW + dpidLong;
203 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
204 FlowBuilder flowBuilder = new FlowBuilder();
206 MatchBuilder matchBuilder = new MatchBuilder();
207 ArrayList<ImmutablePair<String, Long>> macAddrOfPortPairList = segmentationOfPortMap.get(segmentationId);
208 for (ImmutablePair<String, Long> macAddrOfPortPair : macAddrOfPortPairList) {
209 Long ofPort = macAddrOfPortPair.getRight();
210 if (ofPort.equals(currentOfPort)) {
214 MatchUtils.createInPortMatch(matchBuilder, dpidLong, ofPort);
215 matchBuilder = MatchUtils.createEthSrcDestMatch(matchBuilder, new MacAddress(macAddrOfPortPair.getLeft()),
216 new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00"));
217 flowBuilder.setMatch(matchBuilder.build());
218 // Add Flow Attributes
219 String flowName = "ProviderNetwork_BC_Router_" + dpidLong + "_" + ofPort;
220 final FlowId flowId = new FlowId(flowName);
221 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
222 .setPriority(PRIORITY_5).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
225 List<Instruction> outputInstructions = new ArrayList<Instruction>();
226 int instructionIndex = 0;
227 for (ImmutablePair<String, Long> macAddressOfPortPair : macAddrOfPortPairList) {
228 if (ofPort.equals(macAddressOfPortPair.getRight())) {
231 InstructionUtils.createOutputPortInstruction(instructionIndex, dpidLong, macAddressOfPortPair.getRight(),
236 Instruction outputPortInstruction = InstructionUtils.createVlanOutputPortInstructions(new InstructionBuilder(),
237 dpidLong, patchPort, outputInstructions, new VlanId(Integer.valueOf(segmentationId)))
238 .setOrder(0).setKey(new InstructionKey(0)).build();
239 // Add InstructionsBuilder to FlowBuilder
240 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
241 writeFlow(flowBuilder, nodeBuilder);
243 List<Instruction> outputInstructions = new ArrayList<Instruction>();
244 int instructionIndex = 0;
245 for (ImmutablePair<String, Long> ofPortMacAddrPair : macAddrOfPortPairList) {
246 Long cachedOfPort = ofPortMacAddrPair.getRight();
247 if (cachedOfPort.equals(ofPort) || cachedOfPort.equals(currentOfPort)) {
250 InstructionUtils.createOutputPortInstruction(instructionIndex, dpidLong, cachedOfPort, outputInstructions);
253 Instruction outputPortInstruction = InstructionUtils.createVlanOutputPortInstructions(new InstructionBuilder(),
254 dpidLong, patchPort, outputInstructions, new VlanId(Integer.valueOf(segmentationId)))
255 .setOrder(0).setKey(new InstructionKey(0)).build();
256 // Add InstructionsBuilder to FlowBuilder
257 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
258 writeFlow(flowBuilder, nodeBuilder);
264 * Write or remove the flows for forward the packets from one router to another routers (Unicast flow)
265 * Sample flow: table=100, priority=4,in_port=2,dl_dst=fa:16:3e:4b:cc:0a actions=output:8
267 private void programProviderUnicastFlowOfRouters(Long dpidLong, String segmentationId, Long ofPort, Long patchPort,
268 String macAddress, boolean write) {
270 String nodeName = OPENFLOW + dpidLong;
271 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
272 FlowBuilder flowBuilder = new FlowBuilder();
273 ArrayList<ImmutablePair<String, Long>> macAddrOfPortPairList = segmentationOfPortMap.get(segmentationId);
275 for (ImmutablePair<String, Long> macAddressOfPortPair : macAddrOfPortPairList) {
276 for (ImmutablePair<String, Long> subMacAddressOfPortPair : macAddrOfPortPairList) {
277 if (macAddressOfPortPair.getLeft().equals(subMacAddressOfPortPair.getLeft())
278 || ((!macAddressOfPortPair.getLeft().equals(macAddress) &&
279 !subMacAddressOfPortPair.getLeft().equals(macAddress)))) {
282 // Create the OF Match using MatchBuilder
283 MatchBuilder currentMatchBuilder = new MatchBuilder();
285 MatchUtils.createInPortMatch(currentMatchBuilder, dpidLong, macAddressOfPortPair.getRight());
286 currentMatchBuilder = MatchUtils.createDestEthMatch(currentMatchBuilder,
287 new MacAddress(subMacAddressOfPortPair.getLeft()), null);
288 flowBuilder.setMatch(currentMatchBuilder.build());
289 // Add Flow Attributes
290 String currentFlowName = "ProviderNetwork_unicast_router_" + dpidLong + "_" +
291 macAddressOfPortPair.getLeft() + "_" + subMacAddressOfPortPair.getLeft();
293 final FlowId flowId = new FlowId(currentFlowName);
294 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
295 .setPriority(PRIORITY_4).setFlowName(currentFlowName).setHardTimeout(0).setIdleTimeout(0);
297 Instruction outputPortInstruction = InstructionUtils.createOutputPortInstructions(new InstructionBuilder(),
298 dpidLong, subMacAddressOfPortPair.getRight()).setOrder(0).setKey(new InstructionKey(0)).build();
299 // Add InstructionsBuilder to FlowBuilder
300 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
301 writeFlow(flowBuilder, nodeBuilder);
305 for (ImmutablePair<String, Long> macAddressOfPortPair : macAddrOfPortPairList) {
306 if (macAddressOfPortPair.getLeft().equals(macAddress)) {
309 // Create the OF Match using MatchBuilder
310 MatchBuilder matchBuilder = new MatchBuilder();
312 MatchUtils.createInPortMatch(matchBuilder, dpidLong, ofPort);
313 matchBuilder = MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(macAddressOfPortPair.getLeft()), null);
314 flowBuilder.setMatch(matchBuilder.build());
315 // Add Flow Attributes
316 String flowName = "ProviderNetwork_unicast_router_" + dpidLong + "_" + macAddress + "_" + macAddressOfPortPair.getLeft();
317 FlowId flowId = new FlowId(flowName);
318 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
319 .setPriority(PRIORITY_4).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
321 removeFlow(flowBuilder, nodeBuilder);
323 MatchUtils.createInPortMatch(matchBuilder, dpidLong, macAddressOfPortPair.getRight());
324 matchBuilder = MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(macAddress), null);
325 flowBuilder.setMatch(matchBuilder.build());
326 // Add Flow Attributes
327 flowName = "ProviderNetwork_unicast_router_" + dpidLong + "_" + macAddressOfPortPair.getLeft() + "_" + macAddress;
328 flowId = new FlowId(flowName);
329 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
330 .setPriority(PRIORITY_4).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
332 removeFlow(flowBuilder, nodeBuilder);
335 } catch (Exception e) {
336 LOG.error("Error while writing/removing unicast flow of routers. dpidLong = {}, patchPort={}, write = {}."
337 + " Caused due to, {}", dpidLong, patchPort, write, e.getMessage());
342 * Write or remove the flows for forwarding the BC/MC packets to all other router ports connected to same external network.
343 * Sample flow: table=100, priority=4,in_port=1,dl_vlan=100,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=pop_vlan,output:2,output:8
345 private void programProviderBroadAndMultiCastOfExternal(Long dpidLong, String segmentationId, Long ofPort, Long patchPort,
346 String macAddress, boolean write) {
348 String nodeName = OPENFLOW + dpidLong;
349 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
350 FlowBuilder flowBuilder = new FlowBuilder();
351 // Create the OF Match using MatchBuilder
352 MatchBuilder matchBuilder = new MatchBuilder();
354 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
356 MatchUtils.createInPortMatch(matchBuilder, dpidLong, patchPort);
357 matchBuilder = MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
358 new MacAddress("01:00:00:00:00:00"));
359 flowBuilder.setMatch(matchBuilder.build());
360 // Add Flow Attributes
361 String flowName = "ProviderNetwork_BC_External_" + segmentationId + "_" + patchPort;
362 final FlowId flowId = new FlowId(flowName);
363 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
364 .setPriority(PRIORITY_4).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
366 ArrayList<ImmutablePair<String, Long>> macAddrOfPortPairList = segmentationOfPortMap.get(segmentationId);
367 List<Instruction> outputInstructions = new ArrayList<Instruction>();
368 int instructionIndex = 1;
369 for (ImmutablePair<String, Long> ofPortMacAddrPair : macAddrOfPortPairList) {
370 InstructionUtils.createOutputPortInstruction(instructionIndex, dpidLong,
371 ofPortMacAddrPair.getRight(), outputInstructions);
374 Instruction outputPortInstruction =
375 InstructionUtils.createPopOutputPortInstructions(new InstructionBuilder(), dpidLong, null, outputInstructions)
377 .setKey(new InstructionKey(0))
379 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
380 writeFlow(flowBuilder, nodeBuilder);
382 ArrayList<ImmutablePair<String, Long>> macAddrOfPortPairList = segmentationOfPortMap.get(segmentationId);
383 if (macAddrOfPortPairList == null || macAddrOfPortPairList.isEmpty()) {
384 removeFlow(flowBuilder, nodeBuilder);
386 List<Instruction> outputInstructions = new ArrayList<Instruction>();
387 int instructionIndex = 1;
388 for (ImmutablePair<String, Long> ofPortMacAddrPair : macAddrOfPortPairList) {
389 InstructionUtils.createOutputPortInstruction(instructionIndex, dpidLong, ofPortMacAddrPair.getRight(),
393 Instruction outputPortInstruction = InstructionUtils.createPopOutputPortInstructions(new InstructionBuilder(),
394 dpidLong, null, outputInstructions).setOrder(0).setKey(new InstructionKey(0)).build();
395 // Add InstructionsBuilder to FlowBuilder
396 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
397 writeFlow(flowBuilder, nodeBuilder);
400 } catch (Exception e) {
401 LOG.error("Error while writing/removing BC/MC flow of external interface. dpidLong = {}, patchPort={}, write = {}."
402 +" Caused due to, {}", dpidLong, patchPort, write, e.getMessage());
408 * Write or remove the flows for forwarding unicast packets from router to external Gateway.
409 * Sample flow: table=100, priority=2,in_port=2,dl_src=fa:16:3e:ff:9c:57 actions=push_vlan:0x8100,set_field:4196- >vlan_vid,output:1
411 private void programProviderUnicastFlowOfExternal(Long dpidLong, String segmentationId, Long ofPort, Long patchPort,
412 String macAddress, boolean write) {
414 String nodeName = OPENFLOW + dpidLong;
415 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
416 FlowBuilder flowBuilder = new FlowBuilder();
417 // Create the OF Match using MatchBuilder
418 MatchBuilder matchBuilder = new MatchBuilder();
420 MatchUtils.createInPortMatch(matchBuilder, dpidLong, ofPort);
421 MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(macAddress));
422 flowBuilder.setMatch(matchBuilder.build());
423 // Add Flow Attributes
424 String flowName = "ProviderNetwork_unicast_external_" + dpidLong + "_" + ofPort;
425 final FlowId flowId = new FlowId(flowName);
426 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
427 .setPriority(PRIORITY_2).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
429 // Set the Output Port/Iface
430 Instruction outputPortInstruction = InstructionUtils.createPushVlanInstruction(new InstructionBuilder(),
431 dpidLong, patchPort, new VlanId(Integer.valueOf(segmentationId)), new ArrayList<>())
432 .setOrder(0).setKey(new InstructionKey(0)).build();
433 // Add InstructionsBuilder to FlowBuilder
434 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
435 writeFlow(flowBuilder, nodeBuilder);
437 removeFlow(flowBuilder, nodeBuilder);
439 } catch (Exception e) {
440 LOG.error("Error while writing/removing unicast flow of external gateway. dpidLong = {}, write = {}."
441 +" Caused due to, {}", dpidLong, write, e.getMessage());
446 * Write or remove the flows for forwarding unicast packets from external Gateway to router.
447 * Sample flow: table=100, priority=4,in_port=1,dl_vlan=100,dl_dst=fa:16:3e:ff:9c:57 actions=pop_vlan,output:2
449 private void programProviderUnicastFlowFromExternal(Long dpidLong, String segmentationId,
450 Long ofPort, Long patchPort, String macAddress,
451 Map<String, Set<String>> vlanProviderCache, boolean write) {
453 String nodeName = OPENFLOW + dpidLong;
454 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
455 FlowBuilder flowBuilder = new FlowBuilder();
456 ArrayList<ImmutablePair<String, Long>> macAddrOfPortPairList = segmentationOfPortMap.get(segmentationId);
457 // Create the OF Match using MatchBuilder
458 MatchBuilder matchBuilder = new MatchBuilder();
460 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
462 MatchUtils.createInPortMatch(matchBuilder, dpidLong, patchPort);
463 matchBuilder = MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(macAddress), null);
464 flowBuilder.setMatch(matchBuilder.build());
465 // Add Flow Attributes
466 String flowName = "ProviderNetwork_unicast_ext_int" + segmentationId + "_" + ofPort;
467 final FlowId flowId = new FlowId(flowName);
468 flowBuilder.setId(flowId).setBarrier(true).setTableId(getTable()).setKey(new FlowKey(flowId))
469 .setPriority(PRIORITY_4).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
471 // Set the Output Port/Iface
472 Instruction outputPortInstruction = InstructionUtils.createPopOutputPortInstructions(new InstructionBuilder(),
473 dpidLong, ofPort, null).setOrder(0).setKey(new InstructionKey(0)).build();
474 // Add InstructionsBuilder to FlowBuilder
475 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
476 writeFlow(flowBuilder, nodeBuilder);
478 removeFlow(flowBuilder, nodeBuilder);
480 } catch (Exception e) {
481 LOG.error("Error while writing/removing unicast flow of external gateway to router. dpidLong = {}, patchPort={}, write = {}."
482 + "Caused due to, {}", dpidLong, patchPort, write, e.getMessage());
487 * Write or remove the flows for external bridge.
488 * Sample flow: cookie=0x0, duration=4831.827s, table=0, n_packets=1202, n_bytes=56476, priority=4,in_port=3,
489 * dl_src=fa:16:3e:74:a9:2e actions=push_vlan:0x8100,set_field:4196 vlan_vid,NORMAL
491 private void programProviderNetworkForExternal(Long dpidLong, String segmentationId,
492 Long patchExtPort, String macAddress,
493 Map<String, Set<String>> vlanProviderCache, boolean write) {
495 String nodeName = OPENFLOW + dpidLong;
496 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
497 FlowBuilder flowBuilder = new FlowBuilder();
498 // Create the OF Match using MatchBuilder
499 MatchBuilder matchBuilder = new MatchBuilder();
501 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
503 MatchUtils.createInPortMatch(matchBuilder, dpidLong, patchExtPort);
504 flowBuilder.setMatch(matchBuilder.build());
505 // Add Flow Attributes
506 String flowName = "ProviderNetwork_pushVLAN_" + dpidLong + "_" + segmentationId;
507 final FlowId flowId = new FlowId(flowName);
508 flowBuilder.setId(flowId).setBarrier(true).setTableId((short) 0).setKey(new FlowKey(flowId))
509 .setPriority(PRIORITY_4).setFlowName(flowName).setHardTimeout(0).setIdleTimeout(0);
511 LOG.debug("In programProviderNetworkPushVlan macAddress:" + macAddress
512 + "segmentationId:" + segmentationId);
513 Set<String> lstMacAddress = new HashSet<String>();
514 if (vlanProviderCache != null && !vlanProviderCache.isEmpty() && vlanProviderCache.containsKey(segmentationId)) {
515 lstMacAddress = vlanProviderCache.get(segmentationId);
517 lstMacAddress = new HashSet<String>();
518 vlanProviderCache.put(segmentationId, lstMacAddress);
520 lstMacAddress.add(macAddress);
521 Instruction normalInstruction = InstructionUtils.createNormalInstructions(
522 FlowUtils.getNodeName(dpidLong), new InstructionBuilder()).
523 setOrder(0).setKey(new InstructionKey(0)).build();
524 // Add InstructionsBuilder to FlowBuilder
525 InstructionUtils.setFlowBuilderInstruction(flowBuilder, normalInstruction);
526 writeFlow(flowBuilder, nodeBuilder);
528 Set<String> lstMacAddress = new HashSet<String>();
529 if (vlanProviderCache != null && !vlanProviderCache.isEmpty() && vlanProviderCache.containsKey(segmentationId)) {
530 lstMacAddress = vlanProviderCache.get(segmentationId);
531 lstMacAddress.remove(macAddress);
533 if (lstMacAddress == null || lstMacAddress.isEmpty()) {
534 vlanProviderCache.remove(segmentationId);
536 boolean isSegmentationIdExist = vlanProviderCache.containsKey(segmentationId);
537 if (!isSegmentationIdExist) {
538 removeFlow(flowBuilder, nodeBuilder);
540 //removeFlow(flowBuilder, nodeBuilder);
542 } catch (Exception e) {
543 LOG.error("Error while writing/removing push vlan instruction flow. dpidLong = {}, patchPort={}, write = {}."
544 + "Caused due to, {}", dpidLong, patchExtPort, write, e.getMessage());
549 * Write or remove the flows for drop instructions based on flag value actions.
550 * Sample flow: table=0, n_packets=0, n_bytes=0, priority=2,in_port=3 actions=drop
552 private void programProviderNetworkDrop(Long dpidLong, Long patchExtPort,
553 Map<String, Set<String>> vlanProviderCache, boolean write) {
555 String nodeName = OPENFLOW + dpidLong;
556 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
557 FlowBuilder flowBuilder = new FlowBuilder();
558 // Create the OF Match using MatchBuilder
559 MatchBuilder matchBuilder = new MatchBuilder();
561 MatchUtils.createInPortMatch(matchBuilder, dpidLong, patchExtPort);
562 flowBuilder.setMatch(matchBuilder.build());
563 // Add Flow Attributes
564 String flowName = "ProviderNetwork_drop_" + dpidLong + "_" + patchExtPort;
565 final FlowId flowId = new FlowId(flowName);
566 flowBuilder.setId(flowId).setBarrier(true).setTableId((short) 0)
567 .setKey(new FlowKey(flowId)).setPriority(PRIORITY_2).setFlowName(flowName)
568 .setHardTimeout(0).setIdleTimeout(0);
570 // Call the InstructionBuilder Methods Containing Actions
571 Instruction dropInstruction = InstructionUtils.createDropInstructions(new InstructionBuilder())
573 .setKey(new InstructionKey(0))
575 // Add InstructionsBuilder to FlowBuilder
576 InstructionUtils.setFlowBuilderInstruction(flowBuilder, dropInstruction);
577 writeFlow(flowBuilder, nodeBuilder);
579 if (vlanProviderCache.isEmpty()) {
580 removeFlow(flowBuilder, nodeBuilder);
583 } catch (Exception e) {
584 LOG.error("Error while writing/removing drop instruction flow. dpidLong = {}, patchPort={}, write = {}."
585 + "Caused due to, {}", dpidLong, patchExtPort, write, e.getMessage());
589 private void populateSegmentationCache() {
591 Map<String, String> networkUUIDSegIdMap = new ConcurrentHashMap<String, String>();
592 for (Node node : nodeCacheManager.getBridgeNodes()) {
593 Node srcBridgeNode = southbound.getBridgeNode(node, configurationService.getIntegrationBridgeName());
594 if (srcBridgeNode != null) {
595 List<OvsdbTerminationPointAugmentation> terminationPointOfBridgeList =
596 southbound.getTerminationPointsOfBridge(srcBridgeNode);
597 for (OvsdbTerminationPointAugmentation intf : terminationPointOfBridgeList) {
598 NeutronPort neutronPort = tenantNetworkManager.getTenantPort(intf);
599 if (neutronPort != null && neutronPort.getDeviceOwner().equalsIgnoreCase(Constants.OWNER_ROUTER_GATEWAY)) {
600 final String macAddress = neutronPort.getMacAddress();
601 final String networkUUID = neutronPort.getNetworkUUID();
602 String providerSegmentationId = networkUUIDSegIdMap.get(networkUUID);
603 if (providerSegmentationId == null) {
604 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
605 providerSegmentationId = neutronNetwork != null ?
606 neutronNetwork.getProviderSegmentationID() : null;
608 if (providerSegmentationId == null || providerSegmentationId.isEmpty()
609 || macAddress == null || macAddress.isEmpty()) {
612 networkUUIDSegIdMap.put(networkUUID, providerSegmentationId);
613 ArrayList<ImmutablePair<String, Long>> macAddrOfPortPairList = segmentationOfPortMap.get(providerSegmentationId);
614 if (macAddrOfPortPairList == null)
616 macAddrOfPortPairList = new ArrayList<ImmutablePair<String, Long>>();
617 segmentationOfPortMap.put(providerSegmentationId, macAddrOfPortPairList);
619 ImmutablePair<String, Long> macAddrOfPortPair = new ImmutablePair<String, Long>(macAddress, intf.getOfport());
620 macAddrOfPortPairList.add(macAddrOfPortPair);
626 catch (Exception e) {
627 LOG.error("Error while populating segmentation mac-ofport cache, due to {} ", e.getMessage());
632 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
633 super.setDependencies(bundleContext.getServiceReference(VlanResponderProvider.class.getName()), this);
634 configurationService =
635 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
637 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
639 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
640 tenantNetworkManager =
641 (TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
645 public void setDependencies(Object impl) {
646 if (impl instanceof INeutronNetworkCRUD) {
647 neutronNetworkCache = (INeutronNetworkCRUD)impl;
649 populateSegmentationCache();