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;
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());
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;
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;
@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);
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.
*/
@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);
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));
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));
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));
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);
}
}
}
@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;
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
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());
// 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();
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)) {
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)) {
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)) {
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;
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;
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;
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) {
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;
import java.net.HttpURLConnection;
import java.util.List;
+import java.util.Map;
/**
* Handle requests for OpenStack Neutron v2.0 LBaaS API calls for
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;
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
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
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
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;
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
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;
}
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;
* 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
*/
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 {
}
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;
+ }
}
*/
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;
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() {
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() {
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;
}
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;
}
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 + "]";
}
}
*/
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,
// --
- 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();
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) {
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
//
{
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);
}
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
}
}
- 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) {
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);
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;
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;
.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,
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;
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;
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;
}
+ /**
+ * @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