Merge "Bug 1806 - Null destination InetAddress in OF13Provider.handleInterfaceUpdate"
authorMadhu Venugopal <mavenugo@gmail.com>
Wed, 24 Sep 2014 20:55:44 +0000 (20:55 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 24 Sep 2014 20:55:44 +0000 (20:55 +0000)
13 files changed:
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/ArpResponderService.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/LoadBalancerService.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/RoutingService.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/Activator.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/LBaaSHandler.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/LBaaSPoolHandler.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/LBaaSPoolMemberHandler.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/NeutronCacheUtils.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/LoadBalancerConfiguration.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/RoutingProvider.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NeutronL3Adapter.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/ActionUtils.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java

index fb431ae65b8c7b0d2ad38e14453d16f658ac633b..700c579a26d195d8ce71b953e3f2a89dc4c25881 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provide
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
@@ -72,6 +73,7 @@ public class ArpResponderService extends AbstractServiceInstance implements ArpP
 
         MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
         MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(Constants.ARP_ETHERTYPE));
+        MatchUtils.createArpDstIpv4Match(matchBuilder, new Ipv4Prefix(ipAddress.getHostAddress()));
 
         // Move Eth Src to Eth Dst
         ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
index 261a95fba13d728e5c291490c1ac9056c5132266..a6ebf1b22ebdf19a944f3a56c7f01d2897ccd29a 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.Node.NodeIDType;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration.LoadBalancerPoolMember;
@@ -45,6 +46,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
@@ -82,6 +84,14 @@ public class LoadBalancerService extends AbstractServiceInstance implements Load
     @Override
     public Status programLoadBalancerPoolMemberRules(Node node,
             LoadBalancerConfiguration lbConfig, LoadBalancerPoolMember member, org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
+        if (lbConfig == null || member == null) {
+            logger.error("Null value for LB config {} or Member {}", lbConfig, member);
+            return new Status(StatusCode.BADREQUEST);
+        }
+        if (!lbConfig.isValid()) {
+            logger.error("LB config is invalid: {}", lbConfig);
+            return new Status(StatusCode.BADREQUEST);
+        }
         if (!node.getType().equals(NodeIDType.OPENFLOW)) {
             logger.trace("Ignoring non-OpenFlow node {} from flow programming", node);
             return new Status(StatusCode.BADREQUEST);
@@ -94,11 +104,11 @@ public class LoadBalancerService extends AbstractServiceInstance implements Load
         nodeBuilder.setKey(new NodeKey(nodeBuilder.getId()));
 
         //Update the multipath rule
-        insertLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig);
+        manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, true);
 
         if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.ADD)) {
-            insertLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig.getVip(), member);
-            insertLoadBalancerMemberReverseRules(nodeBuilder, lbConfig.getVip(), member);
+            manageLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig, member, true);
+            manageLoadBalancerMemberReverseRules(nodeBuilder, lbConfig, member, true);
             return new Status(StatusCode.SUCCESS);
         }
         /* TODO: Delete single member.
@@ -115,6 +125,14 @@ public class LoadBalancerService extends AbstractServiceInstance implements Load
      */
     @Override
     public Status programLoadBalancerRules(Node node, LoadBalancerConfiguration lbConfig, org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
+        if (lbConfig == null) {
+            logger.error("LB config is invalid: {}", lbConfig);
+            return new Status(StatusCode.BADREQUEST);
+        }
+        if (!lbConfig.isValid()) {
+            logger.error("LB config is invalid: {}", lbConfig);
+            return new Status(StatusCode.BADREQUEST);
+        }
         if (!node.getType().equals(NodeIDType.OPENFLOW)) {
             logger.trace("Ignoring non-OpenFlow node {} from flow programming", node);
             return new Status(StatusCode.BADREQUEST);
@@ -126,76 +144,44 @@ public class LoadBalancerService extends AbstractServiceInstance implements Load
         nodeBuilder.setKey(new NodeKey(nodeBuilder.getId()));
 
         if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.ADD)) {
-            insertLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig);
-            insertLoadBalancerVIPRulesSecondPass(nodeBuilder, lbConfig);
-            insertLoadBalancerReverseRules(nodeBuilder, lbConfig);
+            manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, true);
+            manageLoadBalancerVIPRulesSecondPass(nodeBuilder, lbConfig, true);
+            manageLoadBalancerReverseRules(nodeBuilder, lbConfig, true);
             return new Status(StatusCode.SUCCESS);
         }
         else if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.DELETE)) {
-            removeLoadBalancerVIPRules(nodeBuilder, lbConfig);
-            removeLoadBalancerReverseRules(nodeBuilder, lbConfig);
+            manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, false);
+            manageLoadBalancerVIPRulesSecondPass(nodeBuilder, lbConfig, false);
+            manageLoadBalancerReverseRules(nodeBuilder, lbConfig, false);
             return new Status(StatusCode.SUCCESS);
         }
 
         return new Status(StatusCode.NOTIMPLEMENTED);
     }
 
-    private void insertLoadBalancerVIPRulesFirstPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig) {
+    /**
+     * Method to insert/remove default rule for traffic destined to the VIP and no
+     * server selection performed yet
+     * @param nodeBuilder NodeBuilder
+     * @param lbConfig LoadBalancerConfiguration
+     * @param write Boolean to indicate of the flow is to be inserted or removed
+     */
+    private void manageLoadBalancerVIPRulesFirstPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
         MatchBuilder matchBuilder = new MatchBuilder();
         FlowBuilder flowBuilder = new FlowBuilder();
 
-        // Match VIP, and Reg0==0
+        // Match Tunnel-ID, VIP, and Reg0==0
+        if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
+            lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE))
+            MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
+        else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN))
+            MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
+        else
+            return; //Should not get here. TODO: Other types
+
         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(lbConfig.getVip()));
         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, FIRST_PASS_REGA_MATCH_VALUE));
 
-        // Create the OF Actions and Instructions
-        InstructionsBuilder isb = new InstructionsBuilder();
-
-        // Instructions List Stores Individual Instructions
-        List<Instruction> instructions = Lists.newArrayList();
-
-        List<Action> actionList = Lists.newArrayList();
-
-        ActionBuilder ab = new ActionBuilder();
-        ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD_A).build(),
-                BigInteger.valueOf(SECOND_PASS_REGA_MATCH_VALUE)));
-        ab.setOrder(0);
-        ab.setKey(new ActionKey(0));
-        actionList.add(ab.build());
-
-        ab = new ActionBuilder();
-        ab.setAction(ActionUtils.nxMultipathAction(OfjNxHashFields.NXHASHFIELDSSYMMETRICL4,
-                0, OfjNxMpAlgorithm.NXMPALGMODULON,
-                lbConfig.getMembers().size()-1, //By Nicira-Ext spec, this field is max_link minus 1
-                0L, new DstNxRegCaseBuilder().setNxReg(REG_FIELD_B).build(),
-                0, 31));
-        ab.setOrder(1);
-        ab.setKey(new ActionKey(1));
-        actionList.add(ab.build());
-
-        ab = new ActionBuilder();
-        ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
-        ab.setOrder(2);
-        ab.setKey(new ActionKey(2));
-        actionList.add(ab.build());
-
-        // Create an Apply Action
-        ApplyActionsBuilder aab = new ApplyActionsBuilder();
-        aab.setAction(actionList);
-        InstructionBuilder ib = new InstructionBuilder();
-        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
-
-        // Call the InstructionBuilder Methods Containing Actions
-        ib.setOrder(0);
-        ib.setKey(new InstructionKey(0));
-        instructions.add(ib.build());
-
-        // Add InstructionBuilder to the Instruction(s)Builder List
-        isb.setInstruction(instructions);
-
-        // Add InstructionsBuilder to FlowBuilder
-        flowBuilder.setInstructions(isb.build());
-
         String flowId = "LOADBALANCER_FORWARD_FLOW1_" + lbConfig.getVip();
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
@@ -207,73 +193,95 @@ public class LoadBalancerService extends AbstractServiceInstance implements Load
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        writeFlow(flowBuilder, nodeBuilder);
+
+        if (write) {
+            // Create the OF Actions and Instructions
+            InstructionsBuilder isb = new InstructionsBuilder();
+
+            // Instructions List Stores Individual Instructions
+            List<Instruction> instructions = Lists.newArrayList();
+
+            List<Action> actionList = Lists.newArrayList();
+
+            ActionBuilder ab = new ActionBuilder();
+            ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD_A).build(),
+                    BigInteger.valueOf(SECOND_PASS_REGA_MATCH_VALUE)));
+            ab.setOrder(0);
+            ab.setKey(new ActionKey(0));
+            actionList.add(ab.build());
+
+            ab = new ActionBuilder();
+            ab.setAction(ActionUtils.nxMultipathAction(OfjNxHashFields.NXHASHFIELDSSYMMETRICL4,
+                    0, OfjNxMpAlgorithm.NXMPALGMODULON,
+                    lbConfig.getMembers().size()-1, //By Nicira-Ext spec, this field is max_link minus 1
+                    0L, new DstNxRegCaseBuilder().setNxReg(REG_FIELD_B).build(),
+                    0, 31));
+            ab.setOrder(1);
+            ab.setKey(new ActionKey(1));
+            actionList.add(ab.build());
+
+            ab = new ActionBuilder();
+            ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
+            ab.setOrder(2);
+            ab.setKey(new ActionKey(2));
+            actionList.add(ab.build());
+
+            // Create an Apply Action
+            ApplyActionsBuilder aab = new ApplyActionsBuilder();
+            aab.setAction(actionList);
+            InstructionBuilder ib = new InstructionBuilder();
+            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+            // Call the InstructionBuilder Methods Containing Actions
+            ib.setOrder(0);
+            ib.setKey(new InstructionKey(0));
+            instructions.add(ib.build());
+
+            // Add InstructionBuilder to the Instruction(s)Builder List
+            isb.setInstruction(instructions);
+
+            // Add InstructionsBuilder to FlowBuilder
+            flowBuilder.setInstructions(isb.build());
+
+            writeFlow(flowBuilder, nodeBuilder);
+
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
     }
 
     /*
      * Method to program each rule that matches on Reg0 and Reg1 to insert appropriate header rewriting
-     * rules for all members. This function calls insertLoadBalancerMemberVIPRulesSecondPass in turn.
+     * rules for all members. This function calls manageLoadBalancerMemberVIPRulesSecondPass in turn.
      * @param nodeBuilder Node to insert rule to
      * @param lbConfig Configuration for this LoadBalancer instance
+     * @param write Boolean to indicate of the flow is to be inserted or removed
      */
-    private void insertLoadBalancerVIPRulesSecondPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig) {
+    private void manageLoadBalancerVIPRulesSecondPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
         for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
-            insertLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig.getVip(), entry.getValue());
+            manageLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig, entry.getValue(), write);
         }
     }
 
-    private void insertLoadBalancerMemberVIPRulesSecondPass(NodeBuilder nodeBuilder, String vip, LoadBalancerPoolMember member) {
+    private void manageLoadBalancerMemberVIPRulesSecondPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, LoadBalancerPoolMember member, boolean write) {
+        String vip = lbConfig.getVip();
+
         MatchBuilder matchBuilder = new MatchBuilder();
         FlowBuilder flowBuilder = new FlowBuilder();
 
-        // Match VIP, Reg0==1 and Reg1==Index of member
+        // Match Tunnel-ID, VIP, Reg0==1 and Reg1==Index of member
+        if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
+            lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE))
+            MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
+        else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN))
+            MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
+        else
+            return; //Should not get here. TODO: Other types
+
         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(vip));
         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, SECOND_PASS_REGA_MATCH_VALUE),
                                                new MatchUtils.RegMatch(REG_FIELD_B, (long)member.getIndex()));
 
-        // Create the OF Actions and Instructions
-        InstructionsBuilder isb = new InstructionsBuilder();
-
-        // Instructions List Stores Individual Instructions
-        List<Instruction> instructions = Lists.newArrayList();
-
-        List<Action> actionList = Lists.newArrayList();
-        ActionBuilder ab = new ActionBuilder();
-        ab.setAction(ActionUtils.setDlDstAction(new MacAddress(member.getMAC())));
-        ab.setOrder(0);
-        ab.setKey(new ActionKey(0));
-        actionList.add(ab.build());
-
-        ab = new ActionBuilder();
-        Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(new Ipv4Prefix(member.getIP()));
-        ab.setAction(ActionUtils.setNwDstAction(ipb.build()));
-        ab.setOrder(1);
-        ab.setKey(new ActionKey(1));
-        actionList.add(ab.build());
-
-        // Create an Apply Action
-        ApplyActionsBuilder aab = new ApplyActionsBuilder();
-        aab.setAction(actionList);
-
-        // Call the InstructionBuilder Methods Containing Actions
-        InstructionBuilder ib = new InstructionBuilder();
-        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
-        ib.setOrder(0);
-        ib.setKey(new InstructionKey(0));
-        instructions.add(ib.build());
-
-        // Call the InstructionBuilder Methods Containing Actions
-        ib = this.getMutablePipelineInstructionBuilder();
-        ib.setOrder(1);
-        ib.setKey(new InstructionKey(1));
-        instructions.add(ib.build());
-
-        // Add InstructionBuilder to the Instruction(s)Builder List
-        isb.setInstruction(instructions);
-
-        // Add InstructionsBuilder to FlowBuilder
-        flowBuilder.setInstructions(isb.build());
-
         String flowId = "LOADBALANCER_FORWARD_FLOW2_" + vip + "_" + member.getIP();
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
@@ -285,70 +293,90 @@ public class LoadBalancerService extends AbstractServiceInstance implements Load
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        writeFlow(flowBuilder, nodeBuilder);
+
+        if (write) {
+            // Create the OF Actions and Instructions
+            InstructionsBuilder isb = new InstructionsBuilder();
+
+            // Instructions List Stores Individual Instructions
+            List<Instruction> instructions = Lists.newArrayList();
+
+            List<Action> actionList = Lists.newArrayList();
+            ActionBuilder ab = new ActionBuilder();
+            ab.setAction(ActionUtils.setDlDstAction(new MacAddress(member.getMAC())));
+            ab.setOrder(0);
+            ab.setKey(new ActionKey(0));
+            actionList.add(ab.build());
+
+            ab = new ActionBuilder();
+            Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(new Ipv4Prefix(member.getIP()));
+            ab.setAction(ActionUtils.setNwDstAction(ipb.build()));
+            ab.setOrder(1);
+            ab.setKey(new ActionKey(1));
+            actionList.add(ab.build());
+
+            // Create an Apply Action
+            ApplyActionsBuilder aab = new ApplyActionsBuilder();
+            aab.setAction(actionList);
+
+            // Call the InstructionBuilder Methods Containing Actions
+            InstructionBuilder ib = new InstructionBuilder();
+            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+            ib.setOrder(0);
+            ib.setKey(new InstructionKey(0));
+            instructions.add(ib.build());
+
+            // Call the InstructionBuilder Methods Containing Actions
+            ib = this.getMutablePipelineInstructionBuilder();
+            ib.setOrder(1);
+            ib.setKey(new InstructionKey(1));
+            instructions.add(ib.build());
+
+            // Add InstructionBuilder to the Instruction(s)Builder List
+            isb.setInstruction(instructions);
+
+            // Add InstructionsBuilder to FlowBuilder
+            flowBuilder.setInstructions(isb.build());
+
+            writeFlow(flowBuilder, nodeBuilder);
+
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
     }
 
     /**
      * Method to program all reverse rules that matches member {IP, Protocol, Port} for all members.
-     * This function calls insertLoadBalancerMemberReverseRules in turn.
+     * This function calls manageLoadBalancerMemberReverseRules in turn.
      * @param nodeBuilder Node to insert rule to
      * @param lbConfig Configuration for this LoadBalancer instance
      */
-    private void insertLoadBalancerReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig) {
+    private void manageLoadBalancerReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
         for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
-            insertLoadBalancerMemberReverseRules(nodeBuilder, lbConfig.getVip(), entry.getValue());
+            manageLoadBalancerMemberReverseRules(nodeBuilder, lbConfig, entry.getValue(), write);
         }
     }
 
-    private void insertLoadBalancerMemberReverseRules(NodeBuilder nodeBuilder, String vip, LoadBalancerPoolMember member) {
+    private void manageLoadBalancerMemberReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig,
+            LoadBalancerPoolMember member, boolean write) {
+
+        String vip = lbConfig.getVip();
+        String vmac = lbConfig.getVmac();
+
         MatchBuilder matchBuilder = new MatchBuilder();
         FlowBuilder flowBuilder = new FlowBuilder();
 
-        // Match MemberIP, and Protocol/Port
+        // Match Tunnel-ID, MemberIP, and Protocol/Port
+        if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
+                   lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE))
+            MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
+        else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN))
+            MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
+        else
+            return; //Should not get here. TODO: Other types
+
         MatchUtils.createSrcL3IPv4Match(matchBuilder, new Ipv4Prefix(member.getIP()));
-        if (member.getProtocol().equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP))
-            MatchUtils.createSetSrcTcpMatch(matchBuilder, new PortNumber(LoadBalancerConfiguration.PROTOCOL_HTTP_PORT));
-        else if (member.getProtocol().equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS))
-            MatchUtils.createSetSrcTcpMatch(matchBuilder, new PortNumber(LoadBalancerConfiguration.PROTOCOL_HTTPS_PORT));
-        else //Not possible
-            return;
-
-        // Create the OF Actions and Instructions
-        InstructionsBuilder isb = new InstructionsBuilder();
-
-        // Instructions List Stores Individual Instructions
-        List<Instruction> instructions = Lists.newArrayList();
-
-        List<Action> actionList = Lists.newArrayList();
-        ActionBuilder ab = new ActionBuilder();
-        Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(new Ipv4Prefix(vip));
-        ab.setAction(ActionUtils.setNwSrcAction(ipb.build()));
-        ab.setOrder(0);
-        ab.setKey(new ActionKey(0));
-        actionList.add(ab.build());
-
-        // Create an Apply Action
-        ApplyActionsBuilder aab = new ApplyActionsBuilder();
-        aab.setAction(actionList);
-
-        // Call the InstructionBuilder Methods Containing Actions
-        InstructionBuilder ib = new InstructionBuilder();
-        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
-        ib.setOrder(0);
-        ib.setKey(new InstructionKey(0));
-        instructions.add(ib.build());
-
-        // Call the InstructionBuilder Methods Containing Actions
-        ib = this.getMutablePipelineInstructionBuilder();
-        ib.setOrder(1);
-        ib.setKey(new InstructionKey(1));
-        instructions.add(ib.build());
-
-        // Add InstructionBuilder to the Instruction(s)Builder List
-        isb.setInstruction(instructions);
-
-        // Add InstructionsBuilder to FlowBuilder
-        flowBuilder.setInstructions(isb.build());
+        MatchUtils.createSetSrcTcpMatch(matchBuilder, new PortNumber(member.getPort()));
 
         String flowId = "LOADBALANCER_REVERSE_FLOW_" + vip + "_" + member.getIP();
         flowBuilder.setId(new FlowId(flowId));
@@ -361,78 +389,59 @@ public class LoadBalancerService extends AbstractServiceInstance implements Load
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        writeFlow(flowBuilder, nodeBuilder);
-    }
-
-    /**
-     * Method to remove all rules that are regarding traffic destined to the VIP
-     * (both first and second pass rules)
-     * @param nodeBuilder NodeBuilder
-     * @param lbConfig LoadBalancerConfiguration
-     */
-    private void removeLoadBalancerVIPRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig) {
-        MatchBuilder matchBuilder = new MatchBuilder();
-        FlowBuilder flowBuilder = new FlowBuilder();
-
-        // Match all first pass rules
-        MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(lbConfig.getVip()));
-        MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, FIRST_PASS_REGA_MATCH_VALUE));
-
-        flowBuilder.setMatch(matchBuilder.build());
-        String flowId = "LOADBALANCER_FORWARD_FLOW1_" + lbConfig.getVip();
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY);
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(this.getTable());
-        flowBuilder.setKey(key);
-        removeFlow(flowBuilder, nodeBuilder);
-
-        // Match all second pass rules
-        for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
-            LoadBalancerPoolMember member = entry.getValue();
-            MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, SECOND_PASS_REGA_MATCH_VALUE),
-                                                   new MatchUtils.RegMatch(REG_FIELD_B, (long)member.getIndex()));
-            MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(lbConfig.getVip()));
-
-            flowBuilder.setMatch(matchBuilder.build());
-            flowId = "LOADBALANCER_FORWARD_FLOW2_" + lbConfig.getVip() + "_" + member.getIP();
-            flowBuilder.setId(new FlowId(flowId));
-            key = new FlowKey(new FlowId(flowId));
-            flowBuilder.setKey(key);
-            removeFlow(flowBuilder, nodeBuilder);
-        }
-    }
 
-    /**
-     * Method to remove all reverse traffic from LB member VMs
-     * @param nodeBuilder NodeBuilder
-     * @param lbConfig LoadBalancerConfiguration
-     */
-    private void removeLoadBalancerReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig) {
-        for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
-            LoadBalancerPoolMember member = entry.getValue();
-
-            MatchBuilder matchBuilder = new MatchBuilder();
-            FlowBuilder flowBuilder = new FlowBuilder();
-
-            // Match MemberIP, and Protocol/Port
-            MatchUtils.createSrcL3IPv4Match(matchBuilder, new Ipv4Prefix(member.getIP()));
-            if (member.getProtocol().equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP))
-                MatchUtils.createSetSrcTcpMatch(matchBuilder, new PortNumber(LoadBalancerConfiguration.PROTOCOL_HTTP_PORT));
-            else if (member.getProtocol().equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS))
-                MatchUtils.createSetSrcTcpMatch(matchBuilder, new PortNumber(LoadBalancerConfiguration.PROTOCOL_HTTPS_PORT));
-            else //Not possible
-                return;
-
-            String flowId = "LOADBALANCER_REVERSE_FLOW_" + lbConfig.getVip() + "_" + member.getIP();
-            flowBuilder.setId(new FlowId(flowId));
-            FlowKey key = new FlowKey(new FlowId(flowId));
-            flowBuilder.setMatch(matchBuilder.build());
-            flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY);
-            flowBuilder.setBarrier(true);
-            flowBuilder.setTableId(this.getTable());
-            flowBuilder.setKey(key);
+        if (write) {
+            // Create the OF Actions and Instructions
+            InstructionsBuilder isb = new InstructionsBuilder();
+
+            // Instructions List Stores Individual Instructions
+            List<Instruction> instructions = Lists.newArrayList();
+
+            List<Action> actionList = Lists.newArrayList();
+            ActionBuilder ab = new ActionBuilder();
+            Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(new Ipv4Prefix(vip));
+            ab.setAction(ActionUtils.setNwSrcAction(ipb.build()));
+            ab.setOrder(0);
+            ab.setKey(new ActionKey(0));
+            actionList.add(ab.build());
+
+            /* If a dummy MAC is assigned to the VIP, we use that as the
+             * source MAC for the reverse traffic.
+             */
+            if (vmac != null) {
+                ab = new ActionBuilder();
+                ab.setAction(ActionUtils.setDlDstAction(new MacAddress(vmac)));
+                ab.setOrder(1);
+                ab.setKey(new ActionKey(1));
+                actionList.add(ab.build());
+            }
+
+            // Create an Apply Action
+            ApplyActionsBuilder aab = new ApplyActionsBuilder();
+            aab.setAction(actionList);
+
+            // Call the InstructionBuilder Methods Containing Actions
+            InstructionBuilder ib = new InstructionBuilder();
+            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+            ib.setOrder(0);
+            ib.setKey(new InstructionKey(0));
+            instructions.add(ib.build());
+
+            // Call the InstructionBuilder Methods Containing Actions
+            ib = this.getMutablePipelineInstructionBuilder();
+            ib.setOrder(1);
+            ib.setKey(new InstructionKey(1));
+            instructions.add(ib.build());
+
+            // Add InstructionBuilder to the Instruction(s)Builder List
+            isb.setInstruction(instructions);
+
+            // Add InstructionsBuilder to FlowBuilder
+            flowBuilder.setInstructions(isb.build());
+
+            writeFlow(flowBuilder, nodeBuilder);
+
+        } else {
             removeFlow(flowBuilder, nodeBuilder);
         }
     }
index 592518685c80b21398ce5744485d763462a58ff7..677746e45ee7b7b08fe89ba93066cfde8e627a57 100644 (file)
@@ -53,7 +53,7 @@ public class RoutingService extends AbstractServiceInstance implements RoutingPr
     }
 
     @Override
-    public Status programRouterInterface(Node node, Long dpid, String segmentationId, String macAddress,
+    public Status programRouterInterface(Node node, Long dpid, String sourceSegId, String destSegId, String macAddress,
                                          InetAddress address, int mask, Action action) {
 
         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
@@ -70,7 +70,7 @@ public class RoutingService extends AbstractServiceInstance implements RoutingPr
         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList = Lists.newArrayList();
 
         String prefixString = address.getHostAddress() + "/" + mask;
-        MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+        MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(sourceSegId));
         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(prefixString));
 
         // Set source Mac address
@@ -85,6 +85,12 @@ public class RoutingService extends AbstractServiceInstance implements RoutingPr
         ab.setKey(new ActionKey(1));
         actionList.add(ab.build());
 
+        // Set Destination Tunnel ID
+        ab.setAction(ActionUtils.setTunnelIdAction(new BigInteger(destSegId)));
+        ab.setOrder(2);
+        ab.setKey(new ActionKey(2));
+        actionList.add(ab.build());
+
         // Create Apply Actions Instruction
         aab.setAction(actionList);
         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
@@ -94,8 +100,8 @@ public class RoutingService extends AbstractServiceInstance implements RoutingPr
 
         // Goto Next Table
         ib = getMutablePipelineInstructionBuilder();
-        ib.setOrder(1);
-        ib.setKey(new InstructionKey(1));
+        ib.setOrder(2);
+        ib.setKey(new InstructionKey(2));
         instructions.add(ib.build());
 
         FlowBuilder flowBuilder = new FlowBuilder();
index 48bc3fd14ae628e0b737f0d3f5974634bcfbfa81..3767a5a6593da88d4b188b5ee5fa21a97fdcf56a 100644 (file)
@@ -261,6 +261,8 @@ public class Activator extends ComponentActivatorAbstractBase {
             c.add(createServiceDependency().setService(INeutronLoadBalancerPoolCRUD.class).setRequired(true));
             c.add(createServiceDependency().setService(LoadBalancerProvider.class).setRequired(true));
             c.add(createServiceDependency().setService(ISwitchManager.class).setRequired(true));
+            c.add(createServiceDependency().setService(INeutronNetworkCRUD.class).setRequired(true));
+            c.add(createServiceDependency().setService(INeutronSubnetCRUD.class).setRequired(true));
         }
 
         if (imp.equals(LBaaSPoolHandler.class)) {
@@ -273,9 +275,10 @@ public class Activator extends ComponentActivatorAbstractBase {
             c.add(createServiceDependency().setService(EventDispatcher.class).setRequired(true));
             c.add(createServiceDependency().setService(INeutronPortCRUD.class).setRequired(true));
             c.add(createServiceDependency().setService(INeutronLoadBalancerCRUD.class).setRequired(true));
-            c.add(createServiceDependency().setService(INeutronLoadBalancerPoolCRUD.class).setRequired(true));
             c.add(createServiceDependency().setService(LoadBalancerProvider.class).setRequired(true));
             c.add(createServiceDependency().setService(ISwitchManager.class).setRequired(true));
+            c.add(createServiceDependency().setService(INeutronNetworkCRUD.class).setRequired(true));
+            c.add(createServiceDependency().setService(INeutronSubnetCRUD.class).setRequired(true));
         }
 
         if (imp.equals(LBaaSPoolMemberHandler.class)) {
@@ -291,6 +294,8 @@ public class Activator extends ComponentActivatorAbstractBase {
             c.add(createServiceDependency().setService(INeutronLoadBalancerPoolCRUD.class).setRequired(true));
             c.add(createServiceDependency().setService(LoadBalancerProvider.class).setRequired(true));
             c.add(createServiceDependency().setService(ISwitchManager.class).setRequired(true));
+            c.add(createServiceDependency().setService(INeutronNetworkCRUD.class).setRequired(true));
+            c.add(createServiceDependency().setService(INeutronSubnetCRUD.class).setRequired(true));
         }
 
         if (imp.equals(PortSecurityHandler.class)) {
index 10783851d4e977589338ce5476e7bbe74d5b5268..b958113a650d6988e673afe104ee1b91f95c53d6 100644 (file)
@@ -13,7 +13,9 @@ package org.opendaylight.ovsdb.openstack.netvirt;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerAware;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
@@ -50,6 +52,8 @@ public class LBaaSHandler extends AbstractHandler
     private volatile INeutronLoadBalancerCRUD neutronLBCache;
     private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
     private volatile INeutronPortCRUD neutronPortsCache;
+    private volatile INeutronNetworkCRUD neutronNetworkCache;
+    private volatile INeutronSubnetCRUD neutronSubnetCache;
     private volatile LoadBalancerProvider loadBalancerProvider;
     private volatile ISwitchManager switchManager;
 
@@ -165,7 +169,14 @@ public class LBaaSHandler extends AbstractHandler
         String loadBalancerName = neutronLB.getLoadBalancerName();
         String loadBalancerVip = neutronLB.getLoadBalancerVipAddress();
         String loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
+
         LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
+        Map.Entry<String,String> providerInfo = NeutronCacheUtils.getProviderInformation(neutronNetworkCache, neutronSubnetCache, loadBalancerSubnetID);
+        if (providerInfo != null) {
+            lbConfig.setProviderNetworkType(providerInfo.getKey());
+            lbConfig.setProviderSegmentationId(providerInfo.getValue());
+        }
+        lbConfig.setVmac(NeutronCacheUtils.getMacAddress(neutronPortsCache, loadBalancerVip));
 
         String memberID, memberIP, memberMAC, memberProtocol, memberSubnetID;
         Integer memberPort;
@@ -176,11 +187,9 @@ public class LBaaSHandler extends AbstractHandler
             memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
             if (memberProtocol == null)
                 continue;
-            /*
-             * Only HTTP and HTTPS are supported as of this version
-             * TODO: Support all TCP load-balancers
-             */
-            if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
+
+            if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_TCP) ||
+                  memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
                   memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
                 continue;
             for (NeutronLoadBalancerPoolMember neutronLBPoolMember: members) {
index f745a4b54b5594bbdb30d24014429ebae148c6ca..fb86650a51ce737f7097d1a3303b805fa868fb14 100755 (executable)
@@ -12,8 +12,9 @@ package org.opendaylight.ovsdb.openstack.netvirt;
 
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolAware;
-import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
@@ -30,6 +31,7 @@ import com.google.common.collect.Lists;
 
 import java.net.HttpURLConnection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Handle requests for OpenStack Neutron v2.0 LBaaS API calls for
@@ -43,9 +45,10 @@ public class LBaaSPoolHandler extends AbstractHandler
     private static final Logger logger = LoggerFactory.getLogger(LBaaSPoolHandler.class);
 
     // The implementation for each of these services is resolved by the OSGi Service Manager
-    private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
     private volatile INeutronLoadBalancerCRUD neutronLBCache;
     private volatile INeutronPortCRUD neutronPortsCache;
+    private volatile INeutronNetworkCRUD neutronNetworkCache;
+    private volatile INeutronSubnetCRUD neutronSubnetCache;
     private volatile LoadBalancerProvider loadBalancerProvider;
     private volatile ISwitchManager switchManager;
 
@@ -54,7 +57,8 @@ public class LBaaSPoolHandler extends AbstractHandler
         String poolProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
         if (poolProtocol == null)
             return HttpURLConnection.HTTP_BAD_REQUEST;
-        else if (!(poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
+        else if (!(poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_TCP) ||
+                poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
                 poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
         else
@@ -110,7 +114,8 @@ public class LBaaSPoolHandler extends AbstractHandler
         String poolProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
         if (poolProtocol == null)
             return HttpURLConnection.HTTP_BAD_REQUEST;
-        else if (!(poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
+        else if (!(poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_TCP) ||
+                poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
                 poolProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
         else
@@ -207,7 +212,14 @@ public class LBaaSPoolHandler extends AbstractHandler
             loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
             loadBalancerName = neutronLB.getLoadBalancerName();
             loadBalancerVip = neutronLB.getLoadBalancerVipAddress();
+
             LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
+            Map.Entry<String,String> providerInfo = NeutronCacheUtils.getProviderInformation(neutronNetworkCache, neutronSubnetCache, loadBalancerSubnetID);
+            if (providerInfo != null) {
+                lbConfig.setProviderNetworkType(providerInfo.getKey());
+                lbConfig.setProviderSegmentationId(providerInfo.getValue());
+            }
+            lbConfig.setVmac(NeutronCacheUtils.getMacAddress(neutronPortsCache, loadBalancerVip));
 
             /* Iterate over all the members in this pool and find those in same
              * subnet as the VIP. Those will be included in the lbConfigList
index e9c0ed38ceef8475fea1b58a3a9b84855988db41..bb3d9a0e4fab83648147041e398d08e71496543d 100755 (executable)
@@ -13,7 +13,9 @@ package org.opendaylight.ovsdb.openstack.netvirt;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
@@ -28,6 +30,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Preconditions;
 
 import java.net.HttpURLConnection;
+import java.util.Map;
 
 /**
  * Handle requests for OpenStack Neutron v2.0 LBaaS API calls for
@@ -43,6 +46,8 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
     private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
     private volatile INeutronLoadBalancerCRUD neutronLBCache;
     private volatile INeutronPortCRUD neutronPortsCache;
+    private volatile INeutronNetworkCRUD neutronNetworkCache;
+    private volatile INeutronSubnetCRUD neutronSubnetCache;
     private volatile LoadBalancerProvider loadBalancerProvider;
     private volatile ISwitchManager switchManager;
 
@@ -198,7 +203,8 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
         }
         NeutronLoadBalancerPool neutronLBPool = neutronLBPoolCache.getNeutronLoadBalancerPool(memberPoolID);
         memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
-        if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
+        if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_TCP) ||
+                memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
                 memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
             return null;
 
@@ -217,6 +223,12 @@ public class LBaaSPoolMemberHandler extends AbstractHandler
          * In that case, we create dummy configuration that will not program rules.
          */
         LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
+        Map.Entry<String,String> providerInfo = NeutronCacheUtils.getProviderInformation(neutronNetworkCache, neutronSubnetCache, memberSubnetID);
+        if (providerInfo != null) {
+            lbConfig.setProviderNetworkType(providerInfo.getKey());
+            lbConfig.setProviderSegmentationId(providerInfo.getValue());
+        }
+        lbConfig.setVmac(NeutronCacheUtils.getMacAddress(neutronPortsCache, loadBalancerVip));
 
         /* Extract all other active members and include in LB config
          */
index 9f0984a94992ed51f34f773aafefc5e8087d31ab..bed81ab6dccc1057c8986dc152810a6df9a01312 100755 (executable)
 
 package org.opendaylight.ovsdb.openstack.netvirt;
 
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
 import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
+
+import java.util.AbstractMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 public class NeutronCacheUtils {
 
@@ -47,4 +54,36 @@ public class NeutronCacheUtils {
         }
         return null;
     }
+
+    /**
+     * Look up in the NeutronNetworkCRUD cache and NeutronSubnetCRUD cache for
+     * extracting the provider segmentation_type and segmentation_id
+     * @param subnetId Subnet UUID
+     * @return {Type: ID} pair for that subnet ID
+     */
+    public static Map.Entry<String,String> getProviderInformation(INeutronNetworkCRUD neutronNetworkCache,
+                INeutronSubnetCRUD neutronSubnetCache, String subnetID) {
+
+        String networkID = null;
+
+        List<NeutronSubnet> allSubnets = neutronSubnetCache.getAllSubnets();
+        for (NeutronSubnet subnet: allSubnets) {
+            if (subnet.getID().equals(subnetID)) {
+                networkID = subnet.getNetworkUUID();
+                break;
+            }
+        }
+        if (networkID == null)
+            return null;
+
+        List<NeutronNetwork> allNetworks = neutronNetworkCache.getAllNetworks();
+        for (NeutronNetwork network: allNetworks) {
+            if (network.getID().equals(networkID)) {
+                Map.Entry<String,String> entry = new AbstractMap.SimpleEntry<String, String>(
+                        network.getProviderNetworkType(), network.getProviderSegmentationID());
+                return entry;
+            }
+        }
+        return null;
+    }
 }
index 7965a9e96318bad5979a498bef4ded1ac283910b..e34320ec9bf555c591fe315d6ce54a785df4d8d7 100755 (executable)
@@ -19,10 +19,9 @@ import java.util.Map;
  */
 
 public class LoadBalancerConfiguration {
+    public static final String PROTOCOL_TCP = "TCP";
     public static final String PROTOCOL_HTTP = "HTTP";
     public static final String PROTOCOL_HTTPS = "HTTPS";
-    public static final Integer PROTOCOL_HTTP_PORT = 80;
-    public static final Integer PROTOCOL_HTTPS_PORT = 443;
 
     public class LoadBalancerPoolMember {
         String ipAddr;
@@ -97,6 +96,9 @@ public class LoadBalancerConfiguration {
 
     private String name;
     private String vip;
+    private String vmac; //Used when a dummy neutron port is created for the VIP
+    private String providerNetworkType;
+    private String providerSegmentationId;
     private Map <String, LoadBalancerPoolMember> members;
 
     public LoadBalancerConfiguration() {
@@ -107,12 +109,21 @@ public class LoadBalancerConfiguration {
         this.members = Maps.newHashMap();
         this.name = name;
         this.vip = vip;
+        this.vmac = null;
+    }
+
+    public LoadBalancerConfiguration(String name, String vip, String vmac) {
+        this.members = Maps.newHashMap();
+        this.name = name;
+        this.vip = vip;
+        this.vmac = vmac;
     }
 
     public LoadBalancerConfiguration(LoadBalancerConfiguration lbConfig) {
         this.members = Maps.newHashMap(lbConfig.getMembers());
         this.name = lbConfig.getName();
         this.vip = lbConfig.getVip();
+        this.vmac = lbConfig.getVmac();
     }
 
     public Map<String, LoadBalancerPoolMember> getMembers() {
@@ -144,8 +155,11 @@ public class LoadBalancerConfiguration {
     public boolean isValid() {
         if (members.size() == 0)
             return false;
+        else if (providerNetworkType == null)
+            return false;
         return true;
     }
+
     public void setVip(String vip) {
         this.vip = vip;
     }
@@ -154,6 +168,14 @@ public class LoadBalancerConfiguration {
         return this.vip;
     }
 
+    public void setVmac(String vmac) {
+        this.vmac = vmac;
+    }
+
+    public String getVmac() {
+        return this.vmac;
+    }
+
     public void setName(String name) {
         this.name = name;
     }
@@ -162,9 +184,27 @@ public class LoadBalancerConfiguration {
         return this.name;
     }
 
+    public void setProviderSegmentationId(String providerSegmentationId) {
+        this.providerSegmentationId = providerSegmentationId;
+    }
+
+    public String getProviderSegmentationId() {
+        return this.providerSegmentationId;
+    }
+    public void setProviderNetworkType(String providerNetworkType) {
+        this.providerNetworkType = providerNetworkType;
+    }
+
+    public String getProviderNetworkType() {
+        return this.providerNetworkType;
+    }
+
     @Override
     public String toString() {
-        return "LoadBalancerConfiguration [name=" + name + ", vip=" + vip +
+        return "LoadBalancerConfiguration [name=" + name +
+                ", vip=" + vip + ", vmac=" + vmac +
+                ", networkType=" + providerNetworkType +
+                ", segmentationId=" + providerSegmentationId +
                 ", members=" + members + "]";
     }
 }
index 18b3f3150bf4d63d2c4fecb1322a476761abf3c0..0903bbbc43c59f2100d1697b5daaba18f684c321 100644 (file)
@@ -20,7 +20,7 @@ import java.net.InetAddress;
  */
 public interface RoutingProvider {
 
-    Status programRouterInterface(Node node, Long dpid, String segmentationId, String macAddress,
+    Status programRouterInterface(Node node, Long dpid, String srcSegId, String dstSegId, String macAddress,
                                   InetAddress address, int mask, Action action);
 
     Status programDefaultRouteEntry(Node node, Long dpid, String segmentationId, String macAddress,
index e596b31a0f182873f849d7895313d85651306d35..cc9aeb44ec3abef04ce7379276945ce6676b4022 100644 (file)
@@ -358,45 +358,42 @@ public class NeutronL3Adapter {
 
     // --
 
-    private void programFlowsForNeutronRouterInterface(final NeutronRouter_Interface neutronRouterInterface,
+    private void programFlowsForNeutronRouterInterface(final NeutronRouter_Interface destNeutronRouterInterface,
                                                        Boolean isDelete) {
-        Preconditions.checkNotNull(neutronRouterInterface);
+        Preconditions.checkNotNull(destNeutronRouterInterface);
 
-        final NeutronPort neutronPort = neutronPortCache.getPort(neutronRouterInterface.getPortUUID());
+        final NeutronPort neutronPort = neutronPortCache.getPort(destNeutronRouterInterface.getPortUUID());
         final String macAddress = neutronPort != null ? neutronPort.getMacAddress() : null;
         final List<Neutron_IPs> ipList = neutronPort != null ? neutronPort.getFixedIPs() : null;
-        final NeutronSubnet subnet = neutronSubnetCache.getSubnet(neutronRouterInterface.getSubnetUUID());
+        final NeutronSubnet subnet = neutronSubnetCache.getSubnet(destNeutronRouterInterface.getSubnetUUID());
         final NeutronNetwork neutronNetwork = subnet != null ?
                                               neutronNetworkCache.getNetwork(subnet.getNetworkUUID()) : null;
-        final String providerSegmentationId = neutronNetwork != null ?
-                                              neutronNetwork.getProviderSegmentationID() : null;
+        final String destinationSegmentationId = neutronNetwork != null ?
+                                                 neutronNetwork.getProviderSegmentationID() : null;
         final String gatewayIp = subnet != null ? subnet.getGatewayIP() : null;
         final Boolean isExternal = neutronNetwork != null ? neutronNetwork.getRouterExternal() : Boolean.TRUE;
         final String cidr = subnet != null ? subnet.getCidr() : null;
         final int mask = getMaskLenFromCidr(cidr);
 
         logger.trace("programFlowsForNeutronRouterInterface called for interface {} isDelete {}",
-                     neutronRouterInterface, isDelete);
+                     destNeutronRouterInterface, isDelete);
 
-        if (providerSegmentationId == null || providerSegmentationId.isEmpty() ||
+        if (destinationSegmentationId == null || destinationSegmentationId.isEmpty() ||
             cidr == null || cidr.isEmpty() ||
             macAddress == null || macAddress.isEmpty() ||
             ipList == null || ipList.isEmpty()) {
             logger.debug("programFlowsForNeutronRouterInterface is bailing seg:{} cidr:{} mac:{}  ip:{}",
-                         providerSegmentationId, cidr, macAddress, ipList);
+                         destinationSegmentationId, cidr, macAddress, ipList);
             return;  // done: go no further w/out all the info needed...
         }
 
         final Action action = isDelete ? Action.DELETE : Action.ADD;
 
-        // Keep cache for finding router's mac from network uuid
+        // Keep cache for finding router's mac from network uuid -- add
         //
-        if (isDelete) {
-            networkIdToRouterMacCache.remove(neutronNetwork.getNetworkUUID());
-            subnetIdToRouterInterfaceCache.remove(subnet.getSubnetUUID());
-        } else {
+        if (! isDelete) {
             networkIdToRouterMacCache.put(neutronNetwork.getNetworkUUID(), macAddress);
-            subnetIdToRouterInterfaceCache.put(subnet.getSubnetUUID(), neutronRouterInterface);
+            subnetIdToRouterInterfaceCache.put(subnet.getSubnetUUID(), destNeutronRouterInterface);
         }
 
         List<Node> nodes = connectionService.getNodes();
@@ -406,7 +403,7 @@ public class NeutronL3Adapter {
         for (Node node : nodes) {
             final Long dpid = getDpid(node);
             final Action actionForNode =
-                    tenantNetworkManager.isTenantNetworkPresentInNode(node, providerSegmentationId) ?
+                    tenantNetworkManager.isTenantNetworkPresentInNode(node, destinationSegmentationId) ?
                     action : Action.DELETE;
 
             for (Neutron_IPs neutronIP : ipList) {
@@ -416,8 +413,18 @@ public class NeutronL3Adapter {
                                  node.getID(), ipStr);
                     continue;
                 }
-                programRouterInterfaceStage1(node, dpid, providerSegmentationId, macAddress, ipStr, mask, actionForNode);
-                programStaticArpStage1(node, dpid, providerSegmentationId, macAddress, ipStr, actionForNode);
+
+                // Iterate through all other interfaces and add/remove reflexive flows to this interface
+                //
+                for (NeutronRouter_Interface srcNeutronRouterInterface : subnetIdToRouterInterfaceCache.values()) {
+                    programFlowsForNeutronRouterInterfacePair(node, dpid,
+                                                              srcNeutronRouterInterface, destNeutronRouterInterface,
+                                                              neutronNetwork, destinationSegmentationId,
+                                                              macAddress, ipStr, mask, actionForNode,
+                                                              true /*isReflexsive*/);
+                }
+
+                programStaticArpStage1(node, dpid, destinationSegmentationId, macAddress, ipStr, actionForNode);
             }
 
             // Compute action to be programmed. In the case of rewrite exclusions, we must never program rules
@@ -425,9 +432,9 @@ public class NeutronL3Adapter {
             //
             {
                 final Action actionForRewriteExclusion = isExternal ? Action.DELETE : actionForNode;
-                programIpRewriteExclusionStage1(node, dpid, providerSegmentationId, true /* isInbound */,
+                programIpRewriteExclusionStage1(node, dpid, destinationSegmentationId, true /* isInbound */,
                                                 cidr, actionForRewriteExclusion);
-                programIpRewriteExclusionStage1(node, dpid, providerSegmentationId, false /* isInbound */,
+                programIpRewriteExclusionStage1(node, dpid, destinationSegmentationId, false /* isInbound */,
                                                 cidr, actionForRewriteExclusion);
             }
 
@@ -437,36 +444,127 @@ public class NeutronL3Adapter {
                 final Action actionForNodeDefaultRoute =
                         isExternal ? actionForNode : Action.DELETE;
                 final String defaultGatewayMacAddress = configurationService.getDefaultGatewayMacAddress(node);
-                programDefaultRouteStage1(node, dpid, providerSegmentationId, defaultGatewayMacAddress, gatewayIp,
+                programDefaultRouteStage1(node, dpid, destinationSegmentationId, defaultGatewayMacAddress, gatewayIp,
                                           actionForNodeDefaultRoute);
             }
         }
+
+        // Keep cache for finding router's mac from network uuid -- remove
+        //
+        if (isDelete) {
+            networkIdToRouterMacCache.remove(neutronNetwork.getNetworkUUID());
+            subnetIdToRouterInterfaceCache.remove(subnet.getSubnetUUID());
+        }
+    }
+
+    private void programFlowsForNeutronRouterInterfacePair(final Node node,
+                                                           final Long dpid,
+                                                           final NeutronRouter_Interface srcNeutronRouterInterface,
+                                                           final NeutronRouter_Interface dstNeutronRouterInterface,
+                                                           final NeutronNetwork dstNeutronNetwork,
+                                                           final String destinationSegmentationId,
+                                                           final String dstMacAddress,
+                                                           final String destIpStr,
+                                                           final int destMask,
+                                                           final Action actionForNode,
+                                                           Boolean isReflexsive) {
+        Preconditions.checkNotNull(srcNeutronRouterInterface);
+        Preconditions.checkNotNull(dstNeutronRouterInterface);
+
+        final String sourceSubnetId = srcNeutronRouterInterface.getSubnetUUID();
+        if (sourceSubnetId == null) {
+            logger.error("Could not get provider Subnet ID from router interface {}",
+                         srcNeutronRouterInterface.getID());
+            return;
+        }
+
+        final NeutronSubnet sourceSubnet = neutronSubnetCache.getSubnet(sourceSubnetId);
+        final String sourceNetworkId = sourceSubnet == null ? null : sourceSubnet.getNetworkUUID();
+        if (sourceNetworkId == null) {
+            logger.error("Could not get provider Network ID from subnet {}", sourceSubnetId);
+            return;
+        }
+
+        final NeutronNetwork sourceNetwork = neutronNetworkCache.getNetwork(sourceNetworkId);
+        if (sourceNetwork == null) {
+            logger.error("Could not get provider Network for Network ID {}", sourceNetworkId);
+            return;
+        }
+
+        if (! sourceNetwork.getTenantID().equals(dstNeutronNetwork.getTenantID())) {
+            // Isolate subnets from different tenants within the same router
+            return;
+        }
+        final String sourceSegmentationId = sourceNetwork.getProviderSegmentationID();
+        if (sourceSegmentationId == null) {
+            logger.error("Could not get provider Segmentation ID for Subnet {}", sourceSubnetId);
+            return;
+        }
+        if (sourceSegmentationId.equals(destinationSegmentationId)) {
+            // Skip 'self'
+            return;
+        }
+
+        programRouterInterfaceStage1(node, dpid, sourceSegmentationId, destinationSegmentationId,
+                                     dstMacAddress, destIpStr, destMask, actionForNode);
+
+        // Flip roles src->dst; dst->src
+        if (isReflexsive) {
+            final NeutronPort sourceNeutronPort = neutronPortCache.getPort(srcNeutronRouterInterface.getPortUUID());
+            final String macAddress2 = sourceNeutronPort != null ? sourceNeutronPort.getMacAddress() : null;
+            final List<Neutron_IPs> ipList2 = sourceNeutronPort != null ? sourceNeutronPort.getFixedIPs() : null;
+            final String cidr2 = sourceSubnet.getCidr();
+            final int mask2 = getMaskLenFromCidr(cidr2);
+
+            if (cidr2 == null || cidr2.isEmpty() ||
+                macAddress2 == null || macAddress2.isEmpty() ||
+                ipList2 == null || ipList2.isEmpty()) {
+                logger.trace("programFlowsForNeutronRouterInterfacePair reflexive is bailing seg:{} cidr:{} mac:{} ip:{}",
+                             sourceSegmentationId, cidr2, macAddress2, ipList2);
+                return;  // done: go no further w/out all the info needed...
+            }
+
+            for (Neutron_IPs neutronIP2 : ipList2) {
+                final String ipStr2 = neutronIP2.getIpAddress();
+                if (ipStr2.isEmpty()) {
+                    continue;
+                }
+                programFlowsForNeutronRouterInterfacePair(node, dpid, dstNeutronRouterInterface,
+                                                          srcNeutronRouterInterface,
+                                                          sourceNetwork, sourceSegmentationId,
+                                                          macAddress2, ipStr2, mask2, actionForNode,
+                                                          false /*isReflexsive*/);
+            }
+        }
     }
 
-    private void programRouterInterfaceStage1(Node node, Long dpid, String providerSegmentationId,
+    private void programRouterInterfaceStage1(Node node, Long dpid, String sourceSegmentationId,
+                                              String destinationSegmentationId,
                                               String macAddress, String ipStr, int mask,
                                               Action actionForNode) {
         // Based on the local cache, figure out whether programming needs to occur. To do this, we
         // will look at desired action for node.
         //
-        final String cacheKey = node.toString() + ":" + providerSegmentationId + ":" +
+        final String cacheKey = node.toString() + ":" + sourceSegmentationId + ":" + destinationSegmentationId + ":" +
                                 ipStr + "/" + Integer.toString(mask);
         final Boolean isProgrammed = routerInterfacesCache.contains(cacheKey);
 
         if (actionForNode == Action.DELETE && isProgrammed == Boolean.FALSE) {
-            logger.trace("programRouterInterfaceStage1 for node {} providerId {} mac {} ip {} mask {} action {}" +
-                         " is already done",
-                         node.getNodeIDString(), providerSegmentationId, macAddress, ipStr, mask, actionForNode);
+            logger.trace("programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
+                         "action {} is already done",
+                         node.getNodeIDString(), sourceSegmentationId, destinationSegmentationId,
+                         ipStr, mask, actionForNode);
             return;
         }
         if (actionForNode == Action.ADD && isProgrammed == Boolean.TRUE) {
-            logger.trace("programRouterInterfaceStage1 for node {} providerId {} mac {} ip {} mask {} action {}" +
-                         " is already done",
-                         node.getNodeIDString(), providerSegmentationId, macAddress, ipStr, mask, actionForNode);
+            logger.trace("programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
+                         "action {} is already done",
+                         node.getNodeIDString(), sourceSegmentationId, destinationSegmentationId,
+                         ipStr, mask, actionForNode);
             return;
         }
 
-        Status status = this.programRouterInterfaceStage2(node, dpid, providerSegmentationId,
+        Status status = this.programRouterInterfaceStage2(node, dpid, sourceSegmentationId, destinationSegmentationId,
                                                           macAddress, ipStr, mask, actionForNode);
         if (status.isSuccess()) {
             // Update cache
@@ -480,7 +578,8 @@ public class NeutronL3Adapter {
         }
     }
 
-    private Status programRouterInterfaceStage2(Node node, Long dpid, String providerSegmentationId,
+    private Status programRouterInterfaceStage2(Node node, Long dpid, String sourceSegmentationId,
+                                                String destinationSegmentationId,
                                                 String macAddress,
                                                 String address, int mask,
                                                 Action actionForNode) {
@@ -489,7 +588,7 @@ public class NeutronL3Adapter {
             InetAddress inetAddress = InetAddress.getByName(address);
             status = routingProvider == null ?
                      new Status(StatusCode.SUCCESS) :
-                     routingProvider.programRouterInterface(node, dpid, providerSegmentationId,
+                     routingProvider.programRouterInterface(node, dpid, sourceSegmentationId, destinationSegmentationId,
                                                             macAddress, inetAddress, mask, actionForNode);
         } catch (UnknownHostException e) {
             status = new Status(StatusCode.BADREQUEST);
index 51c9b41f606cb5480725e5f64f8efe069dfa1b9c..7e50f6a91923cec74ae34bed8aa40774caa2e819 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
@@ -28,10 +29,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.DstChoice;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpShaCaseBuilder;
@@ -150,6 +153,20 @@ public final class ActionUtils {
             .build();
     }
 
+    public static Action setTunnelIdAction(BigInteger tunnelId) {
+
+        SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+
+        // Build the Set Tunnel Field Action
+        TunnelBuilder tunnel = new TunnelBuilder();
+        tunnel.setTunnelId(tunnelId);
+        setFieldBuilder.setTunnel(tunnel.build());
+
+        return new SetFieldCaseBuilder()
+                .setSetField(setFieldBuilder.build())
+                .build();
+    }
+
     public static Action nxLoadRegAction(DstChoice dstChoice,
                                          BigInteger value,
                                          int endOffset,
index 42e0adcd503944dffdd9f4d8a027b11a1652347f..08c5987a092c6b0e27496d05bf23b456a73f646f 100644 (file)
@@ -13,6 +13,7 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
@@ -31,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
@@ -61,6 +63,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxTunIdKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.reg.grouping.NxmNxRegBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.tun.id.grouping.NxmNxTunIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.arp.tpa.grouping.NxmOfArpTpaBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.match.rev140714.NxmNxNspKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.match.rev140714.nxm.nx.nsp.grouping.NxmNxNspBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.match.rev140714.NxmNxNsiKey;
@@ -241,6 +244,19 @@ public class MatchUtils {
 
     }
 
+    /**
+     * @param matchBuilder MatchBuilder Object without a match yet
+     * @param dstip        String containing an IPv4 prefix
+     * @return matchBuilder Map Object with a match
+     */
+    public static MatchBuilder createArpDstIpv4Match(MatchBuilder matchBuilder, Ipv4Prefix dstip) {
+        ArpMatchBuilder arpDstMatch = new ArpMatchBuilder();
+        arpDstMatch.setArpTargetTransportAddress(dstip);
+        matchBuilder.setLayer3Match(arpDstMatch.build());
+
+        return matchBuilder;
+    }
+
     /**
      * @param matchBuilder MatchBuilder Object without a match yet
      * @param srcip        String containing an IPv4 prefix