Created
March 2, 2014 14:03
-
-
Save mavenugo/9306979 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright (C) 2013 Red Hat, Inc. | |
* | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v1.0 which accompanies this distribution, | |
* and is available at http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Authors : Madhu Venugopal, Brent Salisbury | |
*/ | |
package org.opendaylight.ovsdb.neutron.provider; | |
import java.math.BigInteger; | |
import java.net.InetAddress; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.concurrent.ExecutionException; | |
import java.util.concurrent.Future; | |
import org.opendaylight.controller.md.sal.common.api.TransactionStatus; | |
import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; | |
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; | |
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; | |
import org.opendaylight.controller.sal.core.Node; | |
import org.opendaylight.controller.sal.utils.HexEncode; | |
import org.opendaylight.controller.sal.utils.ServiceHelper; | |
import org.opendaylight.controller.sal.utils.Status; | |
import org.opendaylight.controller.sal.utils.StatusCode; | |
import org.opendaylight.controller.switchmanager.ISwitchManager; | |
import org.opendaylight.controller.topologymanager.ITopologyManager; | |
import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig; | |
import org.opendaylight.ovsdb.lib.notation.OvsDBMap; | |
import org.opendaylight.ovsdb.lib.notation.OvsDBSet; | |
import org.opendaylight.ovsdb.lib.notation.UUID; | |
import org.opendaylight.ovsdb.lib.table.Bridge; | |
import org.opendaylight.ovsdb.lib.table.Interface; | |
import org.opendaylight.ovsdb.lib.table.Port; | |
import org.opendaylight.ovsdb.neutron.AdminConfigManager; | |
import org.opendaylight.ovsdb.neutron.IMDSALConsumer; | |
import org.opendaylight.ovsdb.neutron.InternalNetworkManager; | |
import org.opendaylight.ovsdb.neutron.TenantNetworkManager; | |
import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal; | |
import org.opendaylight.ovsdb.plugin.OVSDBConfigService; | |
import org.opendaylight.ovsdb.plugin.StatusWithUuid; | |
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp; | |
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.inet.types.rev100924.Uri; | |
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.action.DecNwTtlCaseBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder; | |
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.SetNwTosActionCaseBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.StripVlanActionCaseBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl; | |
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.drop.action._case.DropAction; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder; | |
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.action.action.set.nw.tos.action._case.SetNwTosActionBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.strip.vlan.action._case.StripVlanAction; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.strip.vlan.action._case.StripVlanActionBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; | |
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; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; | |
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.EtherType; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; | |
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.match.layer._4.match.UdpMatchBuilder; | |
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; | |
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; | |
import org.opendaylight.yangtools.yang.common.RpcResult; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
/** | |
* | |
*/ | |
class OF13ProviderManager extends ProviderNetworkManager { | |
private static final Logger logger = LoggerFactory.getLogger(OF13ProviderManager.class); | |
private DataBrokerService dataBrokerService; | |
private static final short TABLE_0_DEFAULT_INGRESS = 0; | |
private static final short TABLE_1_ISOLATE_TENANT = 10; | |
private static final short TABLE_2_LOCAL_FORWARD = 20; | |
@Override | |
public boolean hasPerTenantTunneling() { | |
return false; | |
} | |
private Status getTunnelReadinessStatus (Node node, String tunnelKey) { | |
InetAddress srcTunnelEndPoint = AdminConfigManager.getManager().getTunnelEndPoint(node); | |
if (srcTunnelEndPoint == null) { | |
logger.error("Tunnel Endpoint not configured for Node {}", node); | |
return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node); | |
} | |
if (!InternalNetworkManager.getManager().isInternalNetworkNeutronReady(node)) { | |
logger.error(node+" is not Overlay ready"); | |
return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready"); | |
} | |
if (!TenantNetworkManager.getManager().isTenantNetworkPresentInNode(node, tunnelKey)) { | |
logger.debug(node+" has no VM corresponding to segment "+ tunnelKey); | |
return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey); | |
} | |
return new Status(StatusCode.SUCCESS); | |
} | |
private String getTunnelName(String tunnelType, InetAddress dst) { | |
return tunnelType+"-"+dst.getHostAddress(); | |
} | |
private boolean isTunnelPresent(Node node, String tunnelName, String bridgeUUID) throws Exception { | |
OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); | |
Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID); | |
if (bridge != null) { | |
Set<UUID> ports = bridge.getPorts(); | |
for (UUID portUUID : ports) { | |
Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString()); | |
if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return true; | |
} | |
} | |
return false; | |
} | |
private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) { | |
try { | |
String bridgeUUID = null; | |
String tunnelBridgeName = AdminConfigManager.getManager().getIntegrationBridgeName(); | |
OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); | |
Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName()); | |
if (bridgeTable != null) { | |
for (String uuid : bridgeTable.keySet()) { | |
Bridge bridge = (Bridge)bridgeTable.get(uuid); | |
if (bridge.getName().equals(tunnelBridgeName)) { | |
bridgeUUID = uuid; | |
break; | |
} | |
} | |
} | |
if (bridgeUUID == null) { | |
logger.error("Could not find Bridge {} in {}", tunnelBridgeName, node); | |
return new Status(StatusCode.NOTFOUND, "Could not find "+tunnelBridgeName+" in "+node); | |
} | |
String portName = getTunnelName(tunnelType, dst); | |
if (this.isTunnelPresent(node, portName, bridgeUUID)) { | |
logger.trace("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node); | |
return new Status(StatusCode.SUCCESS); | |
} | |
Port tunnelPort = new Port(); | |
tunnelPort.setName(portName); | |
StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, tunnelPort); | |
if (!statusWithUuid.isSuccess()) { | |
logger.error("Failed to insert Tunnel port {} in {}", portName, bridgeUUID); | |
return statusWithUuid; | |
} | |
String tunnelPortUUID = statusWithUuid.getUuid().toString(); | |
String interfaceUUID = null; | |
int timeout = 6; | |
while ((interfaceUUID == null) && (timeout > 0)) { | |
tunnelPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), tunnelPortUUID); | |
OvsDBSet<UUID> interfaces = tunnelPort.getInterfaces(); | |
if (interfaces == null || interfaces.size() == 0) { | |
// Wait for the OVSDB update to sync up the Local cache. | |
Thread.sleep(500); | |
timeout--; | |
continue; | |
} | |
interfaceUUID = interfaces.toArray()[0].toString(); | |
Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), interfaceUUID); | |
if (intf == null) interfaceUUID = null; | |
} | |
if (interfaceUUID == null) { | |
logger.error("Cannot identify Tunnel Interface for port {}/{}", portName, tunnelPortUUID); | |
return new Status(StatusCode.INTERNALERROR); | |
} | |
Interface tunInterface = new Interface(); | |
tunInterface.setType(tunnelType); | |
OvsDBMap<String, String> options = new OvsDBMap<String, String>(); | |
options.put("key", "flow"); | |
options.put("local_ip", src.getHostAddress()); | |
options.put("remote_ip", dst.getHostAddress()); | |
tunInterface.setOptions(options); | |
Status status = ovsdbTable.updateRow(node, Interface.NAME.getName(), tunnelPortUUID, interfaceUUID, tunInterface); | |
logger.debug("Tunnel {} add status : {}", tunInterface, status); | |
return status; | |
} catch (Exception e) { | |
logger.error("Exception in addTunnelPort", e); | |
return new Status(StatusCode.INTERNALERROR); | |
} | |
} | |
private void connectFreakingTunnelsForTopo (final Node srcNode, final Node dstNode, final String tunnelType, final InetAddress src, final InetAddress dst) throws Exception { | |
new Thread() { | |
public void run() { | |
try { | |
Thread.sleep(5000); | |
Long srcDpid = getIntegrationBridgeOFDPID(srcNode); | |
if (srcDpid == 0L) { | |
logger.error("Openflow Datapath-ID not set for the integration bridge in {}", srcNode); | |
return; | |
} | |
Long dstDpid = getIntegrationBridgeOFDPID(dstNode); | |
if (dstDpid == 0L) { | |
logger.error("Openflow Datapath-ID not set for the integration bridge in {}", dstNode); | |
return; | |
} | |
Long srcTunnelOFPort = getTunnelOFPort(srcNode, tunnelType, dst); | |
Long dstTunnelOFPort = getTunnelOFPort(dstNode, tunnelType, src); | |
if (srcTunnelOFPort <= 0 || dstTunnelOFPort <= 0) { | |
logger.error("Could not identify Openflow port number for Tunnel interface"); | |
return; | |
} | |
String srcNodeName = "MD_SAL|openflow:" + srcDpid; | |
String srcNodeConnector = srcNodeName+":"+srcTunnelOFPort+"@"+srcNodeName; | |
String dstNodeName = "MD_SAL|openflow:" + dstDpid; | |
String dstNodeConnector = dstNodeName+":"+dstTunnelOFPort+"@"+dstNodeName; | |
ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class, | |
"default", this); | |
if (topologyManager == null) { | |
logger.error("Unable to access TopologyManager"); | |
return; | |
} | |
TopologyUserLinkConfig config = new TopologyUserLinkConfig(); | |
config.setName("UL"+srcDpid+""+srcTunnelOFPort+""+dstDpid+""+dstTunnelOFPort); | |
config.setSrcNodeConnector(srcNodeConnector); | |
config.setDstNodeConnector(dstNodeConnector); | |
Status status = topologyManager.addUserLink(config); | |
logger.info("Link {} result {}", config.getName(), status); | |
} catch (Exception e) { | |
logger.error("Exception",e); | |
} | |
} | |
}.start(); | |
} | |
private long getTunnelOFPort(Node node, String tunnelType, InetAddress dst) throws Exception { | |
OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); | |
Set<BigInteger> of_ports; | |
Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName()); | |
if (intfs != null) { | |
for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) { | |
Interface tunIntf = (Interface)row; | |
if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) { | |
of_ports = tunIntf.getOfport(); | |
if (of_ports == null || of_ports.size() <= 0) { | |
logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node); | |
continue; | |
} | |
long tunnelOFPort = ((BigInteger)of_ports.toArray()[0]).longValue(); | |
if (tunnelOFPort <= 0) { | |
logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node); | |
} | |
return tunnelOFPort; | |
} | |
} | |
} | |
return 0; | |
} | |
private void programLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) { | |
/* | |
* Table(0) Rule #3 | |
* ---------------- | |
* Match: VM sMac and Local Ingress Port | |
* Action:Action: Set Tunnel ID and GOTO Local Table (5) | |
*/ | |
writeLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac); | |
/* | |
* Table(0) Rule #4 | |
* ---------------- | |
* Match: Drop any remaining Ingress Local VM Packets | |
* Action: Drop w/ a low priority | |
*/ | |
writeDropSrcIface(dpid, localPort); | |
/* | |
* Table(2) Rule #1 | |
* ---------------- | |
* Match: Match TunID and Destination DL/dMAC Addr | |
* Action: Output Port | |
* table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 | |
*/ | |
writeLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac); | |
/* | |
* Table(2) Rule #2 | |
* ---------------- | |
* Match: Tunnel ID and dMAC (::::FF:FF) | |
* table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \ | |
* actions=output:2,3,4,5 | |
*/ | |
writeLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort); | |
/* | |
* TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment. | |
*/ | |
/* | |
* Table(1) Rule #3 | |
* ---------------- | |
* Match: Any remaining Ingress Local VM Packets | |
* Action: Drop w/ a low priority | |
* ------------------------------------------- | |
* table=1,priority=8192,tun_id=0x5 actions=goto_table:2 | |
*/ | |
writeTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId); | |
/* | |
* Table(2) Rule #3 | |
* ---------------- | |
* Match: Any Remaining Flows w/a TunID | |
* Action: Drop w/ a low priority | |
* table=2,priority=8192,tun_id=0x5 actions=drop | |
*/ | |
writeLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId); | |
} | |
private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) { | |
/* | |
* Table(0) Rule #2 | |
* ---------------- | |
* Match: Ingress Port, Tunnel ID | |
* Action: GOTO Local Table (10) | |
*/ | |
writeTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort); | |
/* | |
* Table(1) Rule #2 | |
* ---------------- | |
* Match: Match Tunnel ID and L2 ::::FF:FF Flooding | |
* Action: Flood to selected destination TEPs | |
* ------------------------------------------- | |
* table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \ | |
* actions=output:10,output:11,goto_table:2 | |
*/ | |
writeTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort); | |
} | |
private void programRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) { | |
/* | |
* Table(1) Rule #1 | |
* ---------------- | |
* Match: Drop any remaining Ingress Local VM Packets | |
* Action: Drop w/ a low priority | |
* ------------------------------------------- | |
* table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \ | |
* actions=output:11,goto_table:2 | |
*/ | |
writeQosTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac); | |
} | |
private Long getIntegrationBridgeOFDPID (Node node) { | |
try { | |
String bridgeName = AdminConfigManager.getManager().getIntegrationBridgeName(); | |
String brIntId = this.getInternalBridgeUUID(node, bridgeName); | |
if (brIntId == null) { | |
logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node); | |
return 0L; | |
} | |
OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); | |
Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId); | |
Set<String> dpids = bridge.getDatapath_id(); | |
if (dpids == null || dpids.size() == 0) return 0L; | |
return Long.valueOf(HexEncode.stringToLong((String) dpids.toArray()[0])); | |
} catch (Exception e) { | |
logger.error("Error finding Integration Bridge's OF DPID", e); | |
return 0L; | |
} | |
} | |
private void programLocalRules (String tunnelType, String segmentationId, Node node, Interface intf) { | |
try { | |
Long dpid = this.getIntegrationBridgeOFDPID(node); | |
if (dpid == 0L) { | |
logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node); | |
return; | |
} | |
Set<BigInteger> of_ports = intf.getOfport(); | |
if (of_ports == null || of_ports.size() <= 0) { | |
logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node); | |
return; | |
} | |
long localPort = ((BigInteger)of_ports.toArray()[0]).longValue(); | |
Map<String, String> externalIds = intf.getExternal_ids(); | |
if (externalIds == null) { | |
logger.error("No external_ids seen in {}", intf); | |
return; | |
} | |
String attachedMac = externalIds.get(TenantNetworkManager.EXTERNAL_ID_VM_MAC); | |
if (attachedMac == null) { | |
logger.error("No AttachedMac seen in {}", intf); | |
return; | |
} | |
programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort); | |
} catch (Exception e) { | |
logger.error("Exception in programming Local Rules for "+intf+" on "+node, e); | |
} | |
} | |
private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node, | |
Interface intf, boolean local) { | |
try { | |
Long dpid = this.getIntegrationBridgeOFDPID(node); | |
if (dpid == 0L) { | |
logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node); | |
return; | |
} | |
OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); | |
Set<BigInteger> of_ports = intf.getOfport(); | |
if (of_ports == null || of_ports.size() <= 0) { | |
logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node); | |
return; | |
} | |
long localPort = ((BigInteger)of_ports.toArray()[0]).longValue(); | |
Map<String, String> externalIds = intf.getExternal_ids(); | |
if (externalIds == null) { | |
logger.error("No external_ids seen in {}", intf); | |
return; | |
} | |
String attachedMac = externalIds.get(TenantNetworkManager.EXTERNAL_ID_VM_MAC); | |
if (attachedMac == null) { | |
logger.error("No AttachedMac seen in {}", intf); | |
return; | |
} | |
Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName()); | |
if (intfs != null) { | |
for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) { | |
Interface tunIntf = (Interface)row; | |
if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) { | |
of_ports = tunIntf.getOfport(); | |
if (of_ports == null || of_ports.size() <= 0) { | |
logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node); | |
continue; | |
} | |
long tunnelOFPort = ((BigInteger)of_ports.toArray()[0]).longValue(); | |
if (tunnelOFPort == -1) { | |
logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node); | |
return; | |
} | |
logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node); | |
if (!local) { | |
programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort); | |
} | |
programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort); | |
return; | |
} | |
} | |
} | |
} catch (Exception e) { | |
logger.error("", e); | |
} | |
} | |
@Override | |
public Status handleInterfaceUpdate(String tunnelType, String tunnelKey, Node srcNode, Interface intf) { | |
ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, "default", this); | |
if (switchManager == null) { | |
logger.error("Unable to identify SwitchManager"); | |
} else { | |
Long dpid = this.getIntegrationBridgeOFDPID(srcNode); | |
if (dpid == 0L) { | |
logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", srcNode); | |
return new Status(StatusCode.NOTFOUND); | |
} | |
Set<Node> ofNodes = switchManager.getNodes(); | |
boolean ofNodeFound = false; | |
if (ofNodes != null) { | |
for (Node ofNode : ofNodes) { | |
if (ofNode.toString().contains(dpid+"")) { | |
logger.debug("Identified the Openflow node via toString {}", ofNode); | |
ofNodeFound = true; | |
break; | |
} | |
} | |
} else { | |
logger.error("Unable to find any Node from SwitchManager"); | |
} | |
if (!ofNodeFound) { | |
logger.error("Unable to find OF Node for {} with update {} on node {}", dpid, intf, srcNode); | |
return new Status(StatusCode.NOTFOUND); | |
} | |
} | |
IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this); | |
List<Node> nodes = connectionService.getNodes(); | |
nodes.remove(srcNode); | |
this.programLocalRules(tunnelType, tunnelKey, srcNode, intf); | |
for (Node dstNode : nodes) { | |
InetAddress src = AdminConfigManager.getManager().getTunnelEndPoint(srcNode); | |
InetAddress dst = AdminConfigManager.getManager().getTunnelEndPoint(dstNode); | |
Status status = addTunnelPort(srcNode, tunnelType, src, dst); | |
if (status.isSuccess()) { | |
this.programTunnelRules(tunnelType, tunnelKey, dst, srcNode, intf, true); | |
} | |
addTunnelPort(dstNode, tunnelType, dst, src); | |
if (status.isSuccess()) { | |
this.programTunnelRules(tunnelType, tunnelKey, src, dstNode, intf, false); | |
try { | |
this.connectFreakingTunnelsForTopo(srcNode, dstNode, tunnelType, src, dst); | |
} catch (Exception e) { | |
logger.error("Exception processing Topology link addtion ", e); | |
} | |
} | |
} | |
return new Status(StatusCode.SUCCESS); | |
} | |
private Status triggerInterfaceUpdates(Node node) { | |
try { | |
OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this); | |
Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName()); | |
if (intfs != null) { | |
for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) { | |
Interface intf = (Interface)row; | |
NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf); | |
logger.debug("Trigger Interface update for {}", intf); | |
if (network != null) { | |
this.handleInterfaceUpdate(network.getProviderNetworkType(), network.getProviderSegmentationID(), node, intf); | |
} | |
} | |
} | |
} catch (Exception e) { | |
logger.error("Error Triggering the lost interface updates for "+ node, e); | |
return new Status(StatusCode.INTERNALERROR, e.getLocalizedMessage()); | |
} | |
return new Status(StatusCode.SUCCESS); | |
} | |
@Override | |
public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) { | |
// TODO Auto-generated method stub | |
return null; | |
} | |
@Override | |
public Status handleInterfaceDelete(String tunnelType, String tunnelKey, Node source, Interface intf, | |
boolean isLastInstanceOnNode) { | |
// TODO Auto-generated method stub | |
return null; | |
} | |
@Override | |
public void initializeFlowRules(Node node) { | |
this.initializeFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName()); | |
this.triggerInterfaceUpdates(node); | |
} | |
/** | |
* @param node | |
* @param bridgeName | |
*/ | |
private void initializeFlowRules(Node node, String bridgeName) { | |
Long dpid = this.getIntegrationBridgeOFDPID(node); | |
if (dpid == 0L) { | |
logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node); | |
return; | |
} | |
/* | |
* Table(0) Rule #1 | |
* ---------------- | |
* Match: LLDP (0x88CCL) | |
* Action: Packet_In to Controller Reserved Port | |
*/ | |
writeLLDPRule(dpid); | |
} | |
/* | |
* Create an LLDP Flow Rule to encapsulate into | |
* a packet_in that is sent to the controller | |
* for topology handling. | |
* Match: Ethertype 0x88CCL | |
* Action: Punt to Controller in a Packet_In msg | |
*/ | |
private void writeLLDPRule(Long dpidLong) { | |
String nodeName = "openflow:" + dpidLong; | |
EtherType etherType = new EtherType(0x88CCL); | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create Match(es) and Set them in the FlowBuilder Object | |
flowBuilder.setMatch(createEtherTypeMatch(matchBuilder, etherType).build()); | |
// Create the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// Call the InstructionBuilder Methods Containing Actions | |
createSendToControllerInstructions(ib); | |
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 = "LLDP"; | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setBarrier(true); | |
flowBuilder.setTableId((short) 0); | |
flowBuilder.setKey(key); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
writeFlow(flowBuilder, nodeBuilder); | |
} | |
/* | |
* (Table:0) Ingress Tunnel Traffic | |
* Match: OpenFlow InPort and Tunnel ID | |
* Action: GOTO Local Table (10) | |
* table=0,tun_id=0x5,in_port=10, actions=goto_table:2 | |
*/ | |
private void writeTunnelIn(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId, Long ofPort) { | |
String nodeName = "openflow:" + dpidLong; | |
BigInteger tunnelId = new BigInteger(segmentationId); | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create Match(es) and Set them in the FlowBuilder Object | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, tunnelId).build()); | |
flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, ofPort).build()); | |
// Create the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// Call the InstructionBuilder Methods Containing Actions | |
createGotoTableInstructions(ib, goToTableId); | |
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 = "TunnelIn_"+segmentationId+"_"+ofPort; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
writeFlow(flowBuilder, nodeBuilder); | |
} | |
/* | |
* (Table:0) Egress VM Traffic Towards TEP | |
* Match: Destination Ethernet Addr and OpenFlow InPort | |
* Instruction: Set TunnelID and GOTO Table Tunnel Table (n) | |
* table=0,in_port=2,dl_src=00:00:00:00:00:01 \ | |
* actions=set_field:5->tun_id,goto_table=1" | |
*/ | |
private void writeLocalInPort(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId, Long inPort, String attachedMac) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create the OF Match using MatchBuilder | |
flowBuilder.setMatch(createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build()); | |
// TODO Broken In_Port Match | |
flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build()); | |
String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
// Instantiate the Builders for the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// GOTO Instuctions Need to be added first to the List | |
createGotoTableInstructions(ib, goToTableId); | |
ib.setOrder(0); | |
ib.setKey(new InstructionKey(0)); | |
instructions.add(ib.build()); | |
// TODO Broken SetTunID | |
createSetTunnelIdInstructions(ib, new BigInteger(segmentationId)); | |
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); | |
} | |
/* | |
* (Table:0) Drop frames sourced from a VM that do not | |
* match the associated MAC address of the local VM. | |
* Match: Low priority anything not matching the VM SMAC | |
* Instruction: Drop | |
* table=0,priority=16384,in_port=1 actions=drop" | |
*/ | |
private void writeDropSrcIface(Long dpidLong, Long inPort) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create the OF Match using MatchBuilder | |
flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build()); | |
// Instantiate the Builders for the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// Call the InstructionBuilder Methods Containing Actions | |
createDropInstructions(ib); | |
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 = "DropFilter_"+inPort; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId((short) 0); | |
flowBuilder.setKey(key); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setPriority(8192); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
writeFlow(flowBuilder, nodeBuilder); | |
} | |
/* | |
* (Table:1) Egress Tunnel Traffic | |
* Match: Destination Ethernet Addr and Local InPort | |
* Instruction: Set TunnelID and GOTO Table Tunnel Table (n) | |
* table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \ | |
* actions=output:10,goto_table:2" | |
*/ | |
private void writeTunnelOut(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId , Long OFPortOut, String attachedMac) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create the OF Match using MatchBuilder | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); | |
flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build()); | |
String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
// Instantiate the Builders for the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// GOTO Instuctions | |
createGotoTableInstructions(ib, goToTableId); | |
ib.setOrder(0); | |
ib.setKey(new InstructionKey(0)); | |
instructions.add(ib.build()); | |
// Set the Output Port/Iface | |
String tenantId = TenantNetworkManager.getManager().getTenantIdForSegmentationId(segmentationId); | |
short flavorId = (short)this.getFlavorForTenant(tenantId); | |
logger.info("TenantId {} for SegmenationId {} & its flavorId {}", tenantId, segmentationId, flavorId); | |
if (flavorId != 0) { | |
createSetDscpTosInstructions(ib, flavorId); | |
ib.setOrder(1); | |
ib.setKey(new InstructionKey(1)); | |
instructions.add(ib.build()); | |
} | |
createOutputPortInstructions(ib, dpidLong, OFPortOut); | |
ib.setOrder(2); | |
ib.setKey(new InstructionKey(2)); | |
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); | |
} | |
/* | |
* (Table:1) Egress Tunnel Traffic | |
* Match: Destination Ethernet Addr and Local InPort | |
* Instruction: Set TunnelID and GOTO Table Tunnel Table (n) | |
* table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \ | |
* actions=output:10,output:11,goto_table:2 | |
*/ | |
private void writeTunnelFloodOut(Long dpidLong, Short writeTable, Short localTable, String segmentationId, Long OFPortOut) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create the OF Match using MatchBuilder | |
// Match TunnelID | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); | |
// Match DMAC | |
flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build()); | |
String flowId = "TunnelFloodOut_"+segmentationId; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setBarrier(true); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setPriority(16384); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
Flow flow = this.getFlow(flowBuilder, nodeBuilder); | |
// Instantiate the Builders for the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// GOTO Instuction | |
createGotoTableInstructions(ib, localTable); | |
ib.setOrder(0); | |
ib.setKey(new InstructionKey(0)); | |
instructions.add(ib.build()); | |
List<Instruction> existingInstructions = null; | |
if (flow != null) { | |
Instructions ins = flow.getInstructions(); | |
if (ins != null) { | |
existingInstructions = ins.getInstruction(); | |
} | |
} /* | |
else { | |
String tenantId = TenantNetworkManager.getManager().getTenantIdForSegmentationId(segmentationId); | |
short flavorId = (short)this.getFlavorForTenant(tenantId); | |
logger.info("TenantId {} for SegmenationId {} & its flavorId {}", tenantId, segmentationId, flavorId); | |
if (flavorId != 0) { | |
createSetDscpTosInstructions(ib, flavorId); | |
ib.setOrder(1); | |
ib.setKey(new InstructionKey(1)); | |
instructions.add(ib.build()); | |
} | |
} | |
*/ | |
// Set the Output Port/Iface | |
createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions); | |
ib.setOrder(2); | |
ib.setKey(new InstructionKey(2)); | |
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); | |
} | |
/* | |
* (Table:1) Table Drain w/ Catch All | |
* Match: Tunnel ID | |
* Action: GOTO Local Table (10) | |
* table=2,priority=8192,tun_id=0x5 actions=drop | |
*/ | |
private void writeTunnelMiss(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create Match(es) and Set them in the FlowBuilder Object | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); | |
// Create the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// Call the InstructionBuilder Methods Containing Actions | |
createGotoTableInstructions(ib, goToTableId); | |
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 = "TunnelMiss_"+segmentationId; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setPriority(8192); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
writeFlow(flowBuilder, nodeBuilder); | |
} | |
/* | |
* (Table:1) Local Broadcast Flood | |
* Match: Tunnel ID and dMAC | |
* Action: Output Port | |
* table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 | |
*/ | |
private void writeLocalUcastOut(Long dpidLong, Short writeTable, String segmentationId, Long localPort, String attachedMac) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create the OF Match using MatchBuilder | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); | |
flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build()); | |
String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
// Instantiate the Builders for the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// Set the Output Port/Iface | |
createOutputPortInstructions(ib, dpidLong, localPort); | |
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); | |
} | |
/* | |
* (Table:1) Local Broadcast Flood | |
* Match: Tunnel ID and dMAC (::::FF:FF) | |
* table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \ | |
* actions=output:2,3,4,5 | |
*/ | |
private void writeLocalBcastOut(Long dpidLong, Short writeTable, String segmentationId, Long localPort) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create the OF Match using MatchBuilder | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); | |
flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build()); | |
String flowId = "BcastOut_"+segmentationId; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setPriority(16384); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
Flow flow = this.getFlow(flowBuilder, nodeBuilder); | |
// Instantiate the Builders for the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
List<Instruction> existingInstructions = null; | |
if (flow != null) { | |
Instructions ins = flow.getInstructions(); | |
if (ins != null) { | |
existingInstructions = ins.getInstruction(); | |
} | |
} | |
// Broken OutPort TODO: localPort needs to be a list of Ports) | |
createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions); | |
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); | |
} | |
/* | |
* (Table:1) Local Table Miss | |
* Match: Any Remaining Flows w/a TunID | |
* Action: Drop w/ a low priority | |
* table=2,priority=8192,tun_id=0x5 actions=drop | |
*/ | |
private void writeLocalTableMiss(Long dpidLong, Short writeTable, String segmentationId) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
// Create Match(es) and Set them in the FlowBuilder Object | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); | |
// Create the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
// Call the InstructionBuilder Methods Containing Actions | |
createDropInstructions(ib); | |
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 = "LocalTableMiss_"+segmentationId; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setKey(key); | |
flowBuilder.setPriority(8192); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
writeFlow(flowBuilder, nodeBuilder); | |
} | |
private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) { | |
IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this); | |
if (mdsalConsumer == null) { | |
logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?"); | |
return null; | |
} | |
dataBrokerService = mdsalConsumer.getDataBrokerService(); | |
if (dataBrokerService == null) { | |
logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller."); | |
return null; | |
} | |
InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory | |
.rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class, | |
new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build(); | |
return (Flow)dataBrokerService.readConfigurationData(path1); | |
} | |
private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) { | |
IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this); | |
if (mdsalConsumer == null) { | |
logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?"); | |
return; | |
} | |
dataBrokerService = mdsalConsumer.getDataBrokerService(); | |
if (dataBrokerService == null) { | |
logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller."); | |
return; | |
} | |
final DataModificationTransaction modification = dataBrokerService.beginTransaction(); | |
//DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction(); | |
InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory | |
.rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class, | |
new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build(); | |
modification.putOperationalData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build()); | |
modification.putOperationalData(path1, flowBuilder.build()); | |
modification.putConfigurationData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build()); | |
modification.putConfigurationData(path1, flowBuilder.build()); | |
Future<RpcResult<TransactionStatus>> commitFuture = modification.commit(); | |
try { | |
RpcResult<TransactionStatus> result = commitFuture.get(); | |
TransactionStatus status = result.getResult(); | |
logger.debug("Transaction Status "+status.toString()+" for Flow "+flowBuilder.getFlowName()); | |
} catch (InterruptedException e) { | |
logger.error(e.getMessage(), e); | |
} catch (ExecutionException e) { | |
logger.error(e.getMessage(), e); | |
} | |
} | |
/** | |
* Create Ingress Port Match dpidLong, inPort | |
* | |
* @param matchBuilder Map matchBuilder MatchBuilder Object without a match | |
* @param dpidLong Long the datapath ID of a switch/node | |
* @param inPort Long ingress port on a switch | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createInPortMatch(MatchBuilder matchBuilder, Long dpidLong, Long inPort) { | |
NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + inPort); | |
logger.debug("createInPortMatch() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, inPort); | |
matchBuilder.setInPort(NodeConnectorId.getDefaultInstance(ncid.getValue())); | |
matchBuilder.setInPort(ncid); | |
return matchBuilder; | |
} | |
/** | |
* Create EtherType Match | |
* | |
* @param matchBuilder Map matchBuilder MatchBuilder Object without a match | |
* @param etherType Long EtherType | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createEtherTypeMatch(MatchBuilder matchBuilder, EtherType etherType) { | |
EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); | |
EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); | |
ethTypeBuilder.setType(new EtherType(etherType)); | |
ethernetMatch.setEthernetType(ethTypeBuilder.build()); | |
matchBuilder.setEthernetMatch(ethernetMatch.build()); | |
return matchBuilder; | |
} | |
/** | |
* Create Ethernet Source Match | |
* | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param sMacAddr String representing a source MAC | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createEthSrcMatch(MatchBuilder matchBuilder, MacAddress sMacAddr) { | |
EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); | |
EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder(); | |
ethSourceBuilder.setAddress(new MacAddress(sMacAddr)); | |
ethernetMatch.setEthernetSource(ethSourceBuilder.build()); | |
matchBuilder.setEthernetMatch(ethernetMatch.build()); | |
return matchBuilder; | |
} | |
/** | |
* Create Ethernet Destination Match | |
* | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param vlanId Integer representing a VLAN ID Integer representing a VLAN ID | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createVlanIdMatch(MatchBuilder matchBuilder, VlanId vlanId) { | |
VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(); | |
VlanIdBuilder vlanIdBuilder = new VlanIdBuilder(); | |
vlanIdBuilder.setVlanId(new VlanId(vlanId)); | |
vlanMatchBuilder.setVlanId(vlanIdBuilder.build()); | |
matchBuilder.setVlanMatch(vlanMatchBuilder.build()); | |
return matchBuilder; | |
} | |
/** | |
* Create Ethernet Destination Match | |
* | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param dMacAddr String representing a destination MAC | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createDestEthMatch(MatchBuilder matchBuilder, MacAddress dMacAddr, MacAddress mask) { | |
EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); | |
EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder(); | |
ethDestinationBuilder.setAddress(new MacAddress(dMacAddr)); | |
if (mask != null) { | |
ethDestinationBuilder.setMask(mask); | |
} | |
ethernetMatch.setEthernetDestination(ethDestinationBuilder.build()); | |
matchBuilder.setEthernetMatch(ethernetMatch.build()); | |
return matchBuilder; | |
} | |
/** | |
* Tunnel ID Match Builder | |
* | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param tunnelId BigInteger representing a tunnel ID | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createTunnelIDMatch(MatchBuilder matchBuilder, BigInteger tunnelId) { | |
TunnelBuilder tunnelBuilder = new TunnelBuilder(); | |
tunnelBuilder.setTunnelId(tunnelId); | |
matchBuilder.setTunnel(tunnelBuilder.build()); | |
return matchBuilder; | |
} | |
/** | |
* Match ICMP code and type | |
* | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param type short representing an ICMP type | |
* @param code short representing an ICMP code | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createICMPv4Match(MatchBuilder matchBuilder, short type, short code) { | |
EthernetMatchBuilder eth = new EthernetMatchBuilder(); | |
EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); | |
ethTypeBuilder.setType(new EtherType(0x0800L)); | |
eth.setEthernetType(ethTypeBuilder.build()); | |
matchBuilder.setEthernetMatch(eth.build()); | |
// Build the IPv4 Match requied per OVS Syntax | |
IpMatchBuilder ipmatch = new IpMatchBuilder(); | |
ipmatch.setIpProtocol((short) 1); | |
matchBuilder.setIpMatch(ipmatch.build()); | |
// Build the ICMPv4 Match | |
Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder(); | |
icmpv4match.setIcmpv4Type(type); | |
icmpv4match.setIcmpv4Code(code); | |
matchBuilder.setIcmpv4Match(icmpv4match.build()); | |
return matchBuilder; | |
} | |
/** | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param dstip String containing an IPv4 prefix | |
* @return matchBuilder Map Object with a match | |
*/ | |
private static MatchBuilder createDstL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix dstip) { | |
EthernetMatchBuilder eth = new EthernetMatchBuilder(); | |
EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); | |
ethTypeBuilder.setType(new EtherType(0x0800L)); | |
eth.setEthernetType(ethTypeBuilder.build()); | |
matchBuilder.setEthernetMatch(eth.build()); | |
Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder(); | |
ipv4match.setIpv4Destination(dstip); | |
matchBuilder.setLayer3Match(ipv4match.build()); | |
return matchBuilder; | |
} | |
/** | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param srcip String containing an IPv4 prefix | |
* @return matchBuilder Map Object with a match | |
*/ | |
private static MatchBuilder createSrcL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix srcip) { | |
EthernetMatchBuilder eth = new EthernetMatchBuilder(); | |
EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); | |
ethTypeBuilder.setType(new EtherType(0x0800L)); | |
eth.setEthernetType(ethTypeBuilder.build()); | |
matchBuilder.setEthernetMatch(eth.build()); | |
Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder(); | |
Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder(); | |
ipv4match.setIpv4Source(srcip); | |
matchBuilder.setLayer3Match(ipv4match.build()); | |
return matchBuilder; | |
} | |
/** | |
* Create Source TCP Port Match | |
* | |
* @param matchBuilder @param matchbuilder MatchBuilder Object without a match yet | |
* @param tcpport Integer representing a source TCP port | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createSetSrcTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) { | |
EthernetMatchBuilder ethType = new EthernetMatchBuilder(); | |
EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); | |
ethTypeBuilder.setType(new EtherType(0x0800L)); | |
ethType.setEthernetType(ethTypeBuilder.build()); | |
matchBuilder.setEthernetMatch(ethType.build()); | |
IpMatchBuilder ipmatch = new IpMatchBuilder(); | |
ipmatch.setIpProtocol((short) 6); | |
matchBuilder.setIpMatch(ipmatch.build()); | |
TcpMatchBuilder tcpmatch = new TcpMatchBuilder(); | |
tcpmatch.setTcpSourcePort(tcpport); | |
matchBuilder.setLayer4Match(tcpmatch.build()); | |
return matchBuilder; | |
} | |
/** | |
* Create Destination TCP Port Match | |
* | |
* @param matchBuilder MatchBuilder Object without a match yet | |
* @param tcpport Integer representing a destination TCP port | |
* @return matchBuilder Map MatchBuilder Object with a match | |
*/ | |
protected static MatchBuilder createSetDstTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) { | |
EthernetMatchBuilder ethType = new EthernetMatchBuilder(); | |
EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); | |
ethTypeBuilder.setType(new EtherType(0x0800L)); | |
ethType.setEthernetType(ethTypeBuilder.build()); | |
matchBuilder.setEthernetMatch(ethType.build()); | |
IpMatchBuilder ipmatch = new IpMatchBuilder(); | |
ipmatch.setIpProtocol((short) 6); | |
matchBuilder.setIpMatch(ipmatch.build()); | |
PortNumber dstport = new PortNumber(tcpport); | |
TcpMatchBuilder tcpmatch = new TcpMatchBuilder(); | |
tcpmatch.setTcpDestinationPort(tcpport); | |
matchBuilder.setLayer4Match(tcpmatch.build()); | |
return matchBuilder; | |
} | |
/** | |
* Create Send to Controller Reserved Port Instruction (packet_in) | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSendToControllerInstructions(InstructionBuilder ib) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
OutputActionBuilder output = new OutputActionBuilder(); | |
output.setMaxLength(56); | |
Uri value = new Uri("CONTROLLER"); | |
output.setOutputNodeConnector(value); | |
ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build()); | |
ab.setOrder(0); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Output Port Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param dpidLong Long the datapath ID of a switch/node | |
* @param port Long representing a port on a switch/node | |
* @return ib InstructionBuilder Map with instructions | |
*/ | |
protected static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port) { | |
NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port); | |
logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, port); | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
OutputActionBuilder oab = new OutputActionBuilder(); | |
oab.setOutputNodeConnector(ncid); | |
ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build()); | |
ab.setOrder(0); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Output Port Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param dpidLong Long the datapath ID of a switch/node | |
* @param port Long representing a port on a switch/node | |
* @return ib InstructionBuilder Map with instructions | |
*/ | |
protected static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port , List<Instruction> instructions) { | |
NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port); | |
logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions); | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
List<Action> existingActions = null; | |
if (instructions != null) { | |
for (Instruction in : instructions) { | |
if (in.getInstruction() instanceof ApplyActionsCase) { | |
existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction()); | |
actionList.addAll(existingActions); | |
} | |
} | |
} | |
OutputActionBuilder oab = new OutputActionBuilder(); | |
oab.setOutputNodeConnector(ncid); | |
ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build()); | |
ab.setOrder(0); | |
ab.setKey(new ActionKey(0)); | |
Action newAction = ab.build(); | |
boolean addNew = true; | |
for (Action action : actionList) { | |
if (action.getAction() instanceof OutputActionCase) { | |
OutputActionCase opAction = (OutputActionCase)action.getAction(); | |
if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) { | |
addNew = false; | |
break; | |
} | |
} | |
} | |
if (addNew) actionList.add(newAction); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set Vlan ID Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param vlanId Integer representing a VLAN ID Integer representing a VLAN ID | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSetVlanInstructions(InstructionBuilder ib, VlanId vlanId) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetVlanIdActionBuilder vl = new SetVlanIdActionBuilder(); | |
vl.setVlanId(vlanId); | |
ab.setAction(new SetVlanIdActionCaseBuilder().setSetVlanIdAction(vl.build()).build()); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set IPv4 Destination Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createStripVlanInstructions(InstructionBuilder ib) { | |
StripVlanActionBuilder stripVlanActionBuilder = new StripVlanActionBuilder(); | |
StripVlanAction vlanAction = stripVlanActionBuilder.build(); | |
ActionBuilder ab = new ActionBuilder(); | |
ab.setAction(new StripVlanActionCaseBuilder().setStripVlanAction(vlanAction).build()); | |
// Add our drop action to a list | |
List<Action> actionList = new ArrayList<Action>(); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set IPv4 Source Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param prefixsrc String containing an IPv4 prefix | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createNwSrcInstructions(InstructionBuilder ib, Ipv4Prefix prefixsrc) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetNwSrcActionBuilder setNwsrcActionBuilder = new SetNwSrcActionBuilder(); | |
Ipv4Builder ipsrc = new Ipv4Builder(); | |
ipsrc.setIpv4Address(prefixsrc); | |
setNwsrcActionBuilder.setAddress(ipsrc.build()); | |
ab.setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwsrcActionBuilder.build()).build()); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set IPv4 Destination Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param prefixdst String containing an IPv4 prefix | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createNwDstInstructions(InstructionBuilder ib, Ipv4Prefix prefixdst) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetNwDstActionBuilder setNwDstActionBuilder = new SetNwDstActionBuilder(); | |
Ipv4Builder ipdst = new Ipv4Builder(); | |
ipdst.setIpv4Address(prefixdst); | |
setNwDstActionBuilder.setAddress(ipdst.build()); | |
ab.setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilder.build()).build()); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Drop Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createDropInstructions(InstructionBuilder ib) { | |
DropActionBuilder dab = new DropActionBuilder(); | |
DropAction dropAction = dab.build(); | |
ActionBuilder ab = new ActionBuilder(); | |
ab.setAction(new DropActionCaseBuilder().setDropAction(dropAction).build()); | |
// Add our drop action to a list | |
List<Action> actionList = new ArrayList<Action>(); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create GOTO Table Instruction Builder | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param tableId short representing a flow table ID short representing a flow table ID | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createGotoTableInstructions(InstructionBuilder ib, short tableId) { | |
GoToTableBuilder gttb = new GoToTableBuilder(); | |
gttb.setTableId(tableId); | |
// Wrap our Apply Action in an InstructionBuilder | |
ib.setInstruction(new GoToTableCaseBuilder().setGoToTable(gttb.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set Tunnel ID Instruction Builder | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param tunnelId BigInteger representing a tunnel ID | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSetTunnelIdInstructions(InstructionBuilder ib, BigInteger tunnelId) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
// Build the Set Tunnel Field Action | |
TunnelBuilder tunnel = new TunnelBuilder(); | |
tunnel.setTunnelId(tunnelId); | |
setFieldBuilder.setTunnel(tunnel.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap the Apply Action in an InstructionBuilder and return | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set Source TCP Port Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param tcpport Integer representing a source TCP port | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSetSrcTCPPort(InstructionBuilder ib, PortNumber tcpport) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
// Build the Destination TCP Port | |
PortNumber tcpsrcport = new PortNumber(tcpport); | |
TcpMatchBuilder tcpmatch = new TcpMatchBuilder(); | |
tcpmatch.setTcpSourcePort(tcpsrcport); | |
setFieldBuilder.setLayer4Match(tcpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(1)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set Destination TCP Port Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param tcpport Integer representing a source TCP port | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSetDstTCPPort(InstructionBuilder ib, PortNumber tcpport) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
// Build the Destination TCP Port | |
PortNumber tcpdstport = new PortNumber(tcpport); | |
TcpMatchBuilder tcpmatch = new TcpMatchBuilder(); | |
tcpmatch.setTcpDestinationPort(tcpdstport); | |
setFieldBuilder.setLayer4Match(tcpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(1)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set Source UDP Port Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param udpport Integer representing a source UDP port | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSetSrcUDPPort(InstructionBuilder ib, PortNumber udpport) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
// Build the Destination TCP Port | |
PortNumber udpsrcport = new PortNumber(udpport); | |
UdpMatchBuilder udpmatch = new UdpMatchBuilder(); | |
udpmatch.setUdpSourcePort(udpsrcport); | |
setFieldBuilder.setLayer4Match(udpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(1)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set Destination UDP Port Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param udpport Integer representing a destination UDP port | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSetDstUDPPort(InstructionBuilder ib, PortNumber udpport) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
// Build the Destination TCP Port | |
PortNumber udpdstport = new PortNumber(udpport); | |
UdpMatchBuilder udpmatch = new UdpMatchBuilder(); | |
udpmatch.setUdpDestinationPort(udpdstport); | |
setFieldBuilder.setLayer4Match(udpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(1)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set ICMP Code Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param code short repesenting an ICMP code | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
private static InstructionBuilder createSetIcmpCodeInstruction(InstructionBuilder ib, short code) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder(); | |
// Build the ICMPv4 Code Match | |
icmpv4match.setIcmpv4Code(code); | |
setFieldBuilder.setIcmpv4Match(icmpv4match.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Set ICMP Code Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
private static InstructionBuilder createSetIcmpTypeInstruction(InstructionBuilder ib, short type) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder(); | |
// Build the ICMPv4 Code Match | |
icmpv4match.setIcmpv4Code(type); | |
setFieldBuilder.setIcmpv4Match(icmpv4match.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(1)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Create Decrement TTL Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
private static InstructionBuilder createDecNwTtlInstructions(InstructionBuilder ib) { | |
DecNwTtlBuilder decNwTtlBuilder = new DecNwTtlBuilder(); | |
DecNwTtl decNwTtl = decNwTtlBuilder.build(); | |
ActionBuilder ab = new ActionBuilder(); | |
ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build()); | |
// Add our drop action to a list | |
List<Action> actionList = new ArrayList<Action>(); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
/** | |
* Set Src Arp MAC | |
*/ | |
private static InstructionBuilder createSrcArpMacInstructions(InstructionBuilder ib, MacAddress macsrc) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
ArpMatchBuilder arpmatch = new ArpMatchBuilder(); | |
ArpSourceHardwareAddressBuilder arpsrc = new ArpSourceHardwareAddressBuilder(); | |
arpsrc.setAddress(macsrc); | |
arpmatch.setArpSourceHardwareAddress(arpsrc.build()); | |
setFieldBuilder.setLayer3Match(arpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
return ib; | |
} | |
/** | |
* Set Dst Arp MAC | |
*/ | |
private static InstructionBuilder createDstArpMacInstructions(InstructionBuilder ib, MacAddress macdst) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
ArpMatchBuilder arpmatch = new ArpMatchBuilder(); | |
ArpTargetHardwareAddressBuilder arpdst = new ArpTargetHardwareAddressBuilder(); | |
arpdst.setAddress(macdst); | |
setFieldBuilder.setLayer3Match(arpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
return ib; | |
} | |
/** | |
* Set Dst Arp IP | |
*/ | |
private static InstructionBuilder createDstArpIpInstructions(InstructionBuilder ib, Ipv4Prefix dstiparp) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
ArpMatchBuilder arpmatch = new ArpMatchBuilder(); | |
arpmatch.setArpTargetTransportAddress(dstiparp); | |
setFieldBuilder.setLayer3Match(arpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
return ib; | |
} | |
/** | |
* Set Src Arp IP | |
*/ | |
private static InstructionBuilder createSrcArpIpInstructions(InstructionBuilder ib, Ipv4Prefix srciparp) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
ArpMatchBuilder arpmatch = new ArpMatchBuilder(); | |
arpmatch.setArpSourceTransportAddress(srciparp); | |
setFieldBuilder.setLayer3Match(arpmatch.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
return ib; | |
} | |
static short[] dscpMap = {0,8,12,16,20,24,28,32,36,40,48,56}; | |
static int[] tosMap = {0,32,48,64,80,96,112,128,144,160,192,224}; | |
/** | |
* Create Set DSCP DS Field Instruction | |
* | |
* @param ib Map InstructionBuilder without any instructions | |
* @param dscpValue Short representing a DSCP ToS bit value | |
* @return ib Map InstructionBuilder with instructions | |
*/ | |
protected static InstructionBuilder createSetDscpTosInstructions(InstructionBuilder ib, Short dscpValue) { | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
IpMatchBuilder ipMatchBuilder = new IpMatchBuilder(); | |
Dscp dscp = new Dscp(dscpMap[dscpValue]); | |
ipMatchBuilder.setIpDscp(dscp); | |
setFieldBuilder.setIpMatch(ipMatchBuilder.build()); | |
ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
actionList.add(ab.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
// Wrap our Apply Action in an Instruction | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
@Override | |
public void initializeOFFlowRules(Node openflowNode) { | |
IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this); | |
List<Node> ovsNodes = connectionService.getNodes(); | |
if (ovsNodes == null) return; | |
for (Node ovsNode : ovsNodes) { | |
Long dpid = this.getIntegrationBridgeOFDPID(ovsNode); | |
logger.debug("Compare openflowNode to OVS br-int node {} vs {}", openflowNode.getID(), dpid); | |
String openflowID = ""+openflowNode.getID(); | |
if (openflowID.contains(""+dpid)) { | |
this.initializeFlowRules(ovsNode, AdminConfigManager.getManager().getIntegrationBridgeName()); | |
this.triggerInterfaceUpdates(ovsNode); | |
} | |
} | |
} | |
private NodeBuilder createNodeBuilder(String nodeId) { | |
NodeBuilder builder = new NodeBuilder(); | |
builder.setId(new NodeId(nodeId)); | |
builder.setKey(new NodeKey(builder.getId())); | |
return builder; | |
} | |
private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder | |
node) { | |
return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, | |
node.getKey()).toInstance(); | |
} | |
private void writeQosTunnelOut(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId , Long OFPortOut, String attachedMac) { | |
String nodeName = "openflow:" + dpidLong; | |
MatchBuilder matchBuilder = new MatchBuilder(); | |
NodeBuilder nodeBuilder = createNodeBuilder(nodeName); | |
FlowBuilder flowBuilder = new FlowBuilder(); | |
flowBuilder.setMatch(createIpQosMatch(matchBuilder, new MacAddress(attachedMac), null).build()); | |
flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); | |
String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac; | |
// Add Flow Attributes | |
flowBuilder.setId(new FlowId(flowId)); | |
FlowKey key = new FlowKey(new FlowId(flowId)); | |
flowBuilder.setStrict(true); | |
flowBuilder.setBarrier(false); | |
flowBuilder.setTableId(writeTable); | |
flowBuilder.setPriority(16384); | |
flowBuilder.setKey(key); | |
flowBuilder.setFlowName(flowId); | |
flowBuilder.setHardTimeout(0); | |
flowBuilder.setIdleTimeout(0); | |
// Instantiate the Builders for the OF Actions and Instructions | |
InstructionBuilder ib = new InstructionBuilder(); | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
// Instructions List Stores Individual Instructions | |
String tenantId = TenantNetworkManager.getManager().getTenantIdForSegmentationId(segmentationId); | |
short flavorId = (short)this.getFlavorForTenant(tenantId); | |
logger.info("TenantId {} for SegmenationId {} & its flavorId {}", tenantId, segmentationId, flavorId); | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
createOutputQosPortInstructions(ib, dpidLong, OFPortOut, flavorId); | |
ib.setOrder(0); | |
ib.setKey(new InstructionKey(0)); | |
instructions.add(ib.build()); | |
// GOTO Instuctions | |
createGotoTableInstructions(ib, goToTableId); | |
ib.setOrder(2); | |
ib.setKey(new InstructionKey(2)); | |
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); | |
} | |
/** | |
* *********** THis is NEW FOR THE APP ************** | |
*/ | |
private static MatchBuilder createIpQosMatch(MatchBuilder matchBuilder, MacAddress dMacAddr, MacAddress mask) { | |
EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); | |
EthernetTypeBuilder ethtype = new EthernetTypeBuilder(); | |
EtherType type = new EtherType(0x0800L); | |
ethernetMatch.setEthernetType(ethtype.setType(type).build()); | |
matchBuilder.setEthernetMatch(ethernetMatch.build()); | |
/* | |
IpMatchBuilder ipmatch = new IpMatchBuilder(); | |
Dscp dscp = new Dscp((short) 3); | |
ipmatch.setIpDscp(dscp); | |
matchBuilder.setIpMatch(ipmatch.build()); | |
*/ | |
EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder(); | |
ethDestinationBuilder.setAddress(new MacAddress(dMacAddr)); | |
if (mask != null) { | |
ethDestinationBuilder.setMask(mask); | |
} | |
ethernetMatch.setEthernetDestination(ethDestinationBuilder.build()); | |
matchBuilder.setEthernetMatch(ethernetMatch.build()); | |
return matchBuilder; | |
} | |
/** | |
* *********** THis is NEW FOR THE APP ************** | |
*/ | |
protected static InstructionBuilder createOutputQosPortInstructions(InstructionBuilder ib, Long dpidLong, Long port, short flavorId) { | |
NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port); | |
logger.debug("createOutputQosPortInstructions() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, port); | |
List<Action> actionList = new ArrayList<Action>(); | |
ActionBuilder ab = new ActionBuilder(); | |
ActionBuilder ab2 = new ActionBuilder(); | |
if (flavorId != 0) { | |
/* | |
SetFieldBuilder setFieldBuilder = new SetFieldBuilder(); | |
IpMatchBuilder ipMatchBuilder = new IpMatchBuilder(); | |
Dscp dscp = new Dscp(dscpMap[flavorId]); | |
ipMatchBuilder.setIpDscp(dscp); | |
setFieldBuilder.setIpMatch(ipMatchBuilder.build()); | |
ab2.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build()); | |
actionList.add(ab2.build()); | |
*/ | |
SetNwTosActionBuilder setNwTosActionBuilder = new SetNwTosActionBuilder(); | |
setNwTosActionBuilder.setTos(tosMap[flavorId]); | |
ab2.setAction(new SetNwTosActionCaseBuilder().setSetNwTosAction(setNwTosActionBuilder.build()).build()); | |
actionList.add(ab2.build()); | |
} | |
OutputActionBuilder oab = new OutputActionBuilder(); | |
oab.setOutputNodeConnector(ncid); | |
ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build()); | |
ab.setOrder(0); | |
ab.setKey(new ActionKey(0)); | |
actionList.add(ab.build()); | |
GoToTableBuilder gtb = new GoToTableBuilder(); | |
gtb.setTableId((short) 20); | |
ib.setInstruction(new GoToTableCaseBuilder().setGoToTable(gtb.build()).build()); | |
// Put our Instruction in a list of Instructions | |
InstructionsBuilder isb = new InstructionsBuilder(); | |
List<Instruction> instructions = new ArrayList<Instruction>(); | |
instructions.add(ib.build()); | |
// Create an Apply Action | |
ApplyActionsBuilder aab = new ApplyActionsBuilder(); | |
aab.setAction(actionList); | |
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); | |
return ib; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment