+ private String getIntModVlanFlowName (int inOFPort, String fromVlan, String toVlan) {
+ return "int_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan;
+ }
+
+ private String getIntDropFlowName (int inOFPort) {
+ return "int_drop_"+inOFPort;
+ }
+
+ private String getNetModVlanFlowName (int inOFPort, String fromVlan, String toVlan) {
+ return "net_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan;
+ }
+
+ private String getNetDropFlowName (int inOFPort) {
+ return "net_drop_"+inOFPort;
+ }
+
+ private String getNetFwdFlowName (int inOFPort, int outOFPort, String vlan) {
+ return "net_fwd_"+vlan+"_"+inOFPort+"_"+outOFPort;
+ }
+
+ private void deleteRule (Node node, Node ofNode, String flowName) {
+ logger.debug("deleteRule: node: {} / {}, flowName: {}", node, ofNode, flowName);
+
+ try {
+ this.deleteStaticFlow(ofNode, flowName);
+ } catch (Exception e) {
+ logger.error("deleteRule: Failed to delete Flow Rule for {} / {}", node, ofNode, e);
+ }
+ }
+
+ /* in_port=p actions=drop */
+ private void programDropRule (Node node, Node ofNode, int inOFPort, String flowName) {
+ logger.debug("programDropRule: node: {} / {}, inOfPort: {}, flowName: {}",
+ node, ofNode, inOFPort, flowName);
+
+ try {
+ FlowConfig flow = new FlowConfig();
+ flow.setName(flowName);
+ flow.setNode(ofNode);
+ flow.setInstallInHw(true);
+ flow.setPriority(DROP_FLOW_PRIORITY+"");
+ flow.setIngressPort(inOFPort+"");
+ List<String> actions = new ArrayList<String>();
+ actions.add(ActionType.DROP+"");
+ flow.setActions(actions);
+ Status status = this.addStaticFlow(ofNode, flow);
+ logger.debug("programDropRule: Flow Programming Status {} for Flow {} on {} / {}",
+ status, flow, node, ofNode);
+ } catch (Exception e) {
+ logger.error("programDropRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e);
+ }
+ }
+
+ /* in_port=p2,dl_vlan=v actions=mod_vlan_vid,[NORMAL|output:p2] */
+ private void programModVlanRule (Node node, Node ofNode, int inOFPort, int outOFPort, String fromVlan,
+ String toVlan, String flowName) {
+ logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, fromVlan: {}, toVlan: {}, flowName: {}",
+ node, ofNode, inOFPort, fromVlan, toVlan, flowName);
+
+ try {
+ FlowConfig flow = new FlowConfig();
+ flow.setName(flowName);
+ flow.setNode(ofNode);
+ flow.setInstallInHw(true);
+ flow.setPriority(INGRESS_TUNNEL_FLOW_PRIORITY+"");
+ flow.setIngressPort(inOFPort+"");
+ flow.setVlanId(fromVlan);
+ List<String> actions = new ArrayList<String>();
+ actions.add(ActionType.SET_VLAN_ID+"="+toVlan);
+ if (outOFPort == -1) {
+ actions.add(ActionType.HW_PATH.toString());
+ } else {
+ actions.add(ActionType.OUTPUT.toString()+"="+outOFPort);
+ }
+ flow.setActions(actions);
+ Status status = this.addStaticFlow(ofNode, flow);
+ logger.debug("programModVlanRule: Flow Programming Status {} for Flow {} on {} / {}",
+ status, flow, node, ofNode);
+ } catch (Exception e) {
+ logger.error("programModVlanRule: Failed to initialize Flow Rule for {} / {}", node, ofNode, e);
+ }
+ }
+
+ /* in_port=p1,dl_vlan=v actions=output:p2 */
+ private void programForwardRule (Node node, Node ofNode, int inOFPort, int outOFPort, String vlan, String flowName) {
+ logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, outOFPort: {}, flowName: {}",
+ node, ofNode, inOFPort, outOFPort, flowName);
+
+ try {
+ FlowConfig flow = new FlowConfig();
+ flow.setName(flowName);
+ flow.setNode(ofNode);
+ flow.setInstallInHw(true);
+ flow.setPriority(EGRESS_TUNNEL_FLOW_PRIORITY + "");
+ flow.setIngressPort(inOFPort + "");
+ flow.setVlanId(vlan);
+ List<String> actions = new ArrayList<String>();
+ actions.add(ActionType.OUTPUT.toString()+"="+outOFPort);
+ flow.setActions(actions);
+ Status status = this.addStaticFlow(ofNode, flow);
+ logger.debug("programForwardRule: Flow Programming Status {} for Flow {} on {} / {}",
+ status, flow, node, ofNode);
+ } catch (Exception e) {
+ logger.error("programForwardRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e);
+ }
+ }
+
+ public int getOFPort (Node node, String portName) {
+ int ofPort = -1;
+ try {
+ OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+ Map<String, Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+ if (intfs != null) {
+ for (Table<?> row : intfs.values()) {
+ Interface intf = (Interface)row;
+ if (intf.getName().equalsIgnoreCase(portName)) {
+ Set<BigInteger> of_ports = intf.getOfport();
+ if (of_ports == null || of_ports.size() <= 0) {
+ logger.error("Could not identify patch port {} on {}", portName, node);
+ continue;
+ }
+ ofPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue();
+ logger.debug("Identified port {} -> OF ({}) on {}", portName, ofPort, node);
+ break;
+ }
+ }
+ }
+ } catch (Exception e) {
+ logger.error("", e);
+ }
+
+ return ofPort;
+ }
+
+ /*
+ * Transient class to return all the vlan network data needed for flow programming.
+ */
+ public class vlanNet {
+ public int patchIntOfPort;
+ public int patchNetOfPort;
+ public int physicalOfPort;
+ public int internalVlan;
+
+ public vlanNet (NeutronNetwork network, Node node, Interface intf) {
+ patchIntOfPort = -1;
+ patchNetOfPort = -1;
+ physicalOfPort = -1;
+ internalVlan = 0;
+
+ initializeVlanNet(network, node, intf);
+ }
+
+ public boolean isValid () {
+ if ((patchIntOfPort != -1) && (patchNetOfPort != -1) && (physicalOfPort != -1) && (internalVlan != -1)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public int getPatchIntOfPort () {
+ return patchIntOfPort;
+ }
+
+ public int getPatchNetOfPort () {
+ return patchNetOfPort;
+ }
+
+ public int getphysicalOfPort () {
+ return physicalOfPort;
+ }
+
+ public int getInternalVlan () {
+ return internalVlan;
+ }
+
+ public void initializeVlanNet (NeutronNetwork network, Node node, Interface intf) {
+ internalVlan = TenantNetworkManager.getManager().getInternalVlan(node, network.getNetworkUUID());
+ if (internalVlan == 0) {
+ logger.debug("No InternalVlan provisioned for Tenant Network {}", network.getNetworkUUID());
+ return;
+ }
+
+ /* Get ofports for patch ports and physical interface. */
+ String patchToNetworkName = AdminConfigManager.getManager().getPatchToNetwork();
+ String patchToIntegrationName = AdminConfigManager.getManager().getPatchToIntegration();
+ String physNetName = AdminConfigManager.getManager().getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
+
+ patchIntOfPort = getOFPort(node, patchToNetworkName);
+ if (patchIntOfPort == -1) {
+ logger.error("Cannot identify {} interface on {}", patchToNetworkName, node);
+ return;
+ }
+
+ patchNetOfPort = getOFPort(node, patchToIntegrationName);
+ if (patchNetOfPort == -1) {
+ logger.error("Cannot identify {} interface on {}", patchToIntegrationName, node);
+ return;
+ }
+
+ physicalOfPort = getOFPort(node, physNetName);
+ if (physicalOfPort == -1) {
+ logger.error("Cannot identify {} interface on {}", physNetName, node);
+ return;
+ }
+ }
+ }
+
+ private Node getOFNode (Node node, String bridgeName) {
+ String brUUID = InternalNetworkManager.getManager().getInternalBridgeUUID(node, bridgeName);
+ if (brUUID == null) {
+ logger.error("getOFNode: Unable to find {} UUID on node {}", bridgeName, node);
+ return null;
+ }
+
+ try {
+ OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+ Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brUUID);
+ Set<String> dpids = bridge.getDatapath_id();
+ if (dpids == null || dpids.size() == 0) {
+ return null;
+ }
+ Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
+ Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
+ return ofNode;
+ } catch (Exception e) {
+ logger.error("deleteRule: Failed to delete Flow Rule for {}", node, e);
+ }
+
+ return null;
+ }
+
+ /*
+ * Vlan isolation uses a patch port between br-int and br-net. Anything received on one end of
+ * the patch is piped to the other end of the patch so the incoming packets from the network would
+ * arrive untouched at the patch port on br-int.
+ *
+ * Program OF1.0 Flow rules on br-net in the ingress direction from the network
+ * and egress direction towards the network.
+ * The logic is to simply match on the incoming patch OF-Port and internal vlan,
+ * rewrite the internal vlan to the external vlan and forward out the physical port.
+ * There is also a flow to match the externally tagged packets from the physical port
+ * rewrite the external tag to the internal tag and forward to the patch port.
+ *
+ * priority=100,in_port=1,dl_vlan=1 actions=mod_vlan_vid:2001,output:2
+ * priority=100,in_port=2,dl_vlan=2001 actions=mod_vlan_vid:1actions=output:1
+ */
+
+ private void programVlanRules (NeutronNetwork network, Node node, Interface intf) {
+ vlanNet vlanNet = new vlanNet(network, node, intf);
+ if (vlanNet.isValid()) {
+ String netBrName = AdminConfigManager.getManager().getNetworkBridgeName();
+ String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"");
+ String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID());
+
+ Node netOFNode = getOFNode(node, netBrName);
+ if (netOFNode == null) {
+ logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node);
+ return;
+ }
+
+ /* Program flows on br-net */
+ deleteRule(node, netOFNode, "NORMAL");
+ programModVlanRule(node, netOFNode, vlanNet.getPatchNetOfPort(), vlanNet.getphysicalOfPort(),
+ vlanNet.getInternalVlan()+"", network.getProviderSegmentationID(), intModVlanFlowName);
+ programModVlanRule(node, netOFNode, vlanNet.getphysicalOfPort(), vlanNet.getPatchNetOfPort(),
+ network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"", netModVlanFlowName);
+ }
+ }
+
+ private void removeVlanRules (NeutronNetwork network, Node node, Interface intf) {
+ vlanNet vlanNet = new vlanNet(network, node, intf);
+ if (vlanNet.isValid()) {
+ String netBrName = AdminConfigManager.getManager().getNetworkBridgeName();
+ String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"");
+ String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID());
+
+ Node netOFNode = getOFNode(node, netBrName);
+ if (netOFNode == null) {
+ logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node);
+ return;
+ }
+
+ deleteRule(node, netOFNode, intModVlanFlowName);
+ deleteRule(node, netOFNode, netModVlanFlowName);
+ }
+ }
+