import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.neutron.spi.NeutronNetwork;
+import org.opendaylight.neutron.spi.NeutronPort;
+import org.opendaylight.neutron.spi.NeutronSecurityGroup;
+import org.opendaylight.neutron.spi.Neutron_IPs;
import org.opendaylight.ovsdb.openstack.netvirt.MdsalHelper;
import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
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.yangtools.yang.binding.InstanceIdentifier;
return dpid;
}
+ /**
+ * Returns true is the network if of type GRE or VXLAN
+ *
+ * @param networkType The type of the network
+ * @return returns true if the network is a tunnel
+ */
+ private boolean isTunnel(String networkType)
+ {
+ return (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) || networkType.equalsIgnoreCase
+ (NetworkHandler.NETWORK_TYPE_VXLAN))? true:false;
+ }
+
+ /**
+ * Returns true if the network is of type vlan.
+ *
+ * @param networkType The type of the network
+ * @return returns true if the network is a vlan
+ */
+ private boolean isVlan(String networkType)
+ {
+ return networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)? true:false;
+ }
+
private void programLocalRules (String networkType, String segmentationId, Node node,
OvsdbTerminationPointAugmentation intf) {
logger.debug("programLocalRules: node: {}, intf: {}, networkType: {}, segmentationId: {}",
}
/* Program local rules based on network type */
- if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+ if (isVlan(networkType)) {
logger.debug("Program local vlan rules for interface {}", intf.getName());
programLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
}
+ if ((isTunnel(networkType)|| isVlan(networkType))) {
+ logger.debug("programLocalRules: Program fixed security group rules for interface {}", intf.getName());
+ // Get the DHCP port for the subnet to which the interface belongs to.
+ NeutronPort dhcpPort = securityServicesManager.getDHCPServerPort(intf);
+ if (null != dhcpPort) {
+ boolean isComputePort =securityServicesManager.isComputePort(intf);
+ boolean isLastPortinBridge = securityServicesManager.isLastPortinBridge(node, intf);
+ boolean isLastPortinSubnet =false;
+ List<Neutron_IPs> srcAddressList = null;
+ if(isComputePort) {
+ isLastPortinSubnet = securityServicesManager.isLastPortinSubnet(node, intf);
+ srcAddressList = securityServicesManager.getIpAddress(node, intf);
+ if (null == srcAddressList) {
+ logger.warn("programLocalRules: No Ip address assigned {}", intf);
+ return;
+ }
+ }
+ ingressAclProvider.programFixedSecurityACL(dpid,segmentationId, dhcpPort.getMacAddress(), localPort,
+ isLastPortinSubnet,isComputePort, true);
+ egressAclProvider.programFixedSecurityACL(dpid, segmentationId, attachedMac, localPort,
+ srcAddressList, isLastPortinBridge, isComputePort,true);
+ } else {
+ logger.warn("programLocalRules: No DCHP port seen in network of {}", intf);
+ }
+ }
/* If the network type is tunnel based (VXLAN/GRRE/etc) with Neutron Port Security ACLs */
/* TODO SB_MIGRATION */
/*if ((networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) || networkType.equalsIgnoreCase
egressAclProvider.programPortSecurityACL(dpid, segmentationId, attachedMac, localPort,
securityGroupInPort);
}*/
- if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
- networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
+ if (isTunnel(networkType)) {
logger.debug("Program local bridge rules for interface {}, "
+ "dpid: {}, segmentationId: {}, attachedMac: {}, localPort: {}",
intf.getName(), dpid, segmentationId, attachedMac, localPort);
}
/* Program local rules based on network type */
- if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+ if (isVlan(networkType)) {
logger.debug("Remove local vlan rules for interface {}", intf.getName());
removeLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
- } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
- networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
+ } else if (isTunnel(networkType)) {
logger.debug("Remove local bridge rules for interface {}", intf.getName());
removeLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
}
+ if (isTunnel(networkType)|| isVlan(networkType)) {
+ logger.debug("removeLocalRules: Remove fixed security group rules for interface {}", intf.getName());
+ NeutronPort dhcpPort = securityServicesManager.getDHCPServerPort(intf);
+ if (null != dhcpPort) {
+ List<Neutron_IPs> srcAddressList = securityServicesManager.getIpAddress(node, intf);
+ if (null == srcAddressList) {
+ logger.warn("removeLocalRules: No Ip address assigned {}", intf);
+ return;
+ }
+ boolean isLastPortinBridge = securityServicesManager.isLastPortinBridge(node, intf);
+ boolean isComputePort =securityServicesManager.isComputePort(intf);
+ boolean isLastPortinSubnet =false;
+ if (isComputePort)
+ {
+ isLastPortinSubnet = securityServicesManager.isLastPortinSubnet(node, intf);
+ }
+ ingressAclProvider.programFixedSecurityACL(dpid, segmentationId, dhcpPort.getMacAddress(), localPort,
+ isLastPortinSubnet, isComputePort, false);
+ egressAclProvider.programFixedSecurityACL(dpid, segmentationId, attachedMac, localPort,
+ srcAddressList, isLastPortinBridge, isComputePort, false);
+ }else{
+ logger.warn("removeLocalRules: No DCHP port seen in network of {}", intf);
+ }
+ }
} catch (Exception e) {
logger.error("Exception in removing Local Rules for "+intf+" on "+node, e);
}
Node srcBridgeNode = southbound.getBridgeNode(srcNode, configurationService.getIntegrationBridgeName());
programLocalRules(networkType, network.getProviderSegmentationID(), srcBridgeNode, intf);
- if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+ if (isVlan(networkType)) {
programVlanRules(network, srcNode, intf);
- } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
- || networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)){
+ } else if (isTunnel(networkType)){
boolean sourceTunnelStatus = false;
boolean destTunnelStatus = false;
removeLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(),
srcNode, intf);
- if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+ if (isVlan(network.getProviderNetworkType())) {
removeVlanRules(network, srcNode, intf, isLastInstanceOnNode);
- } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
- || network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
+ } else if (isTunnel(network.getProviderNetworkType())) {
for (Node dstNode : nodes.values()) {
InetAddress src = configurationService.getTunnelEndPoint(srcNode);
package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
import java.math.BigInteger;
+import java.net.InetAddress;
+import java.util.Iterator;
import java.util.List;
import org.opendaylight.neutron.spi.NeutronSecurityGroup;
import org.opendaylight.neutron.spi.NeutronSecurityRule;
+import org.opendaylight.neutron.spi.Neutron_IPs;
import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
static final Logger logger = LoggerFactory.getLogger(EgressAclService.class);
+ final int DHCP_SOURCE_PORT = 67;
+ final int DHCP_DESTINATION_PORT = 68;
+ final String HOST_MASK = "/32";
public EgressAclService() {
super(Service.EGRESS_ACL);
}
}
+ @Override
+ public void programFixedSecurityACL(Long dpid, String segmentationId, String attachedMac,
+ long localPort, List<Neutron_IPs> srcAddressList, boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
+ // If it is the only port in the bridge add the rule to allow any DHCP client traffic
+ if (isLastPortinBridge) {
+ egressACLDHCPAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
+ }
+ if(isComputePort) {
+ // add rule to drop the DHCP server traffic originating from the vm.
+ egressACLDHCPDropServerTrafficfromVM(dpid, localPort, write, Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
+ //Adds rule to check legitimate ip/mac pair for each packet from the vm
+ for(Neutron_IPs srcAddress : srcAddressList) {
+ String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
+ egressACLAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix, Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
+ }
+ }
+ }
+
public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
int priority, boolean write) {
}
}
+ /**
+ * Adds flow to allow any DHCP client traffic
+ *
+ * @param dpidLong the dpid
+ * @param write whether to write or delete the flow
+ * @param protoPortMatchPriority the priority
+ */
+ public void egressACLDHCPAllowClientTrafficFromVm(Long dpidLong,
+ boolean write, Integer protoPortMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createDHCPMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT).build());
+ logger.debug("egressACLDHCPAllowClientTrafficFromVm: MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "Egress_DHCP_Client" + "_Permit_";
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("egressACLDHCPAllowClientTrafficFromVm: Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ /**
+ * Adds rule to prevent DHCP spoofing by the vm attached to the port.
+ *
+ * @param dpidLong the dpid
+ * @param localPort the local port
+ * @param write is write or delete
+ * @param protoPortMatchPriority the priority
+ */
+ public void egressACLDHCPDropServerTrafficfromVM(Long dpidLong, long localPort,
+ boolean write, Integer protoPortMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
+ flowBuilder.setMatch(MatchUtils.createDHCPMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT).build());
+
+ logger.debug("egressACLDHCPDropServerTrafficfromVM: MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ InstructionUtils.createDropInstructions(ib);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("egressACLDHCPDropServerTrafficfromVM: Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ /**
+ * Adds rule to check legitimate ip/mac pair for each packet from the vm.
+ *
+ * @param dpidLong the dpid
+ * @param localPort the local port
+ * @param srcIp the vm ip address
+ * @param attachedMac the vm mac address
+ * @param protoPortMatchPriority the priority
+ * @param write is write or delete
+ */
+ public void egressACLAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
+ String attachedMac, String srcIp, Integer protoPortMatchPriority, boolean write) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ MatchUtils.createSrcL3IPv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
+ MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
+ flowBuilder.setMatch(matchBuilder.build());
+
+ logger.debug("egressACLAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("egressACLAllowTrafficFromVmIpMacPair: Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
@Override
public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
}
}
+ @Override
+ public void programFixedSecurityACL(Long dpid, String segmentationId, String dhcpMacAddress,
+ long localPort, boolean isLastPortinSubnet, boolean isComputePort, boolean write){
+ //If this port is the only port in the compute node add the DHCP server rule.
+ if (isLastPortinSubnet && isComputePort ) {
+ ingressACLDHCPAllowServerTraffic(dpid, segmentationId,dhcpMacAddress, write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
+ }
+ }
+
public void ingressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
Integer securityRulePortMin, Integer protoPortMatchPriority) {
}
}
+ /**
+ * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
+ *
+ * @param dpidLong the dpid
+ * @param segmentationId the segmentation id
+ * @param dhcpMacAddress the DHCP server mac address
+ * @param write is write or delete
+ * @param protoPortMatchPriority the priority
+ */
+ private void ingressACLDHCPAllowServerTraffic(Long dpidLong, String segmentationId, String dhcpMacAddress,
+ boolean write, Integer protoPortMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createDHCPServerMatch(matchBuilder, dhcpMacAddress, 67, 68).build());
+ logger.debug("ingressACLDHCPAllowServerTraffic: MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "Ingress_DHCP_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_";
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
@Override
public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
super.setDependencies(bundleContext.getServiceReference(IngressAclProvider.class.getName()), this);
lBaaSHandler.setDependencies(service);
lBaaSPoolHandler.setDependencies(service);
lBaaSPoolMemberHandler.setDependencies(service);
+ securityServices.setDependencies(service);
neutronL3Adapter.setDependencies(service);
}
return service;
/*
* ACL
*/
+ public static final Integer PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP = 61011;
public static final Integer PROTO_MATCH_PRIORITY_DROP = 36006;
public static final Integer PROTO_PORT_MATCH_PRIORITY_DROP = 36005;
public static final Integer PREFIX_MATCH_PRIORITY_DROP = 36004;
public static final Integer PREFIX_PORT_MATCH_PRIORITY_DROP = 36002;
public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP = 36001;
+ public static final Integer PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY = 61012;
public static final Integer PROTO_MATCH_PRIORITY = 61010;
public static final Integer PREFIX_MATCH_PRIORITY = 61009;
public static final Integer PROTO_PREFIX_MATCH_PRIORITY = 61008;
public static final Integer PROTO_PORT_MATCH_PRIORITY = 61007;
public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY = 61007;
+ public static final Integer PROTO_DHCP_SERVER_MATCH_PRIORITY = 61006;
+ public static final Integer PROTO_VM_IP_MAC_MATCH_PRIORITY = 36001;
public static final int TCP_SYN = 0x002;
public static final short INGRESS_ACL = 40; // Flows Destined to the VM Port go here
package org.opendaylight.ovsdb.openstack.netvirt.api;
+import java.util.List;
+
import org.opendaylight.neutron.spi.NeutronSecurityGroup;
+import org.opendaylight.neutron.spi.Neutron_IPs;
/**
* This interface allows egress Port Security flows to be written to devices
*/
public void programPortSecurityACL(Long dpid, String segmentationId, String attachedMac,
long localPort, NeutronSecurityGroup securityGroup);
+ /**
+ * Program fixed egress ACL rules that will be associated with the VM port when a vm is spawned.
+ *
+ * @param dpid the dpid
+ * @param segmentationId the segmentation id
+ * @param attachedMac the attached mac
+ * @param localPort the local port
+ * @param srcAddressList the list of source ip address assigned to vm
+ * @param isLastPortinBridge is this the last port in the bridge
+ * @param isComputePort indicates whether this port is a compute port or not
+ * @param write is this flow writing or deleting
+ */
+ public void programFixedSecurityACL(Long dpid, String segmentationId,String attachedMac,
+ long localPort, List<Neutron_IPs> srcAddressList, boolean isLastPortinBridge, boolean isComputePort, boolean write);
}
*/
public void programPortSecurityACL(Long dpid, String segmentationId, String attachedMac,
long localPort, NeutronSecurityGroup securityGroup);
+ /**
+ * Program fixed ingress ACL rules that will be associated with the VM port when a vm is spawned.
+ * *
+ * @param dpid the dpid
+ * @param segmentationId the segmentation id
+ * @param attachedMac the attached mac
+ * @param localPort the local port
+ * @param isLastPortinSubnet is this the last port in the subnet
+ * @param isComputePort indicates whether this port is a compute port or not
+ * @param write is this flow writing or deleting
+ */
+ public void programFixedSecurityACL(Long dpid, String segmentationId,
+ String attachedMac, long localPort, boolean isLastPortinSubnet, boolean isComputePort, boolean write);
}
package org.opendaylight.ovsdb.openstack.netvirt.api;
+import java.util.List;
+
+import org.opendaylight.neutron.spi.NeutronPort;
import org.opendaylight.neutron.spi.NeutronSecurityGroup;
+import org.opendaylight.neutron.spi.Neutron_IPs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
/**
* Open vSwitch isolates Tenant Networks using VLANs on the Integration Bridge
* @return the security group in port
*/
public NeutronSecurityGroup getSecurityGroupInPort(OvsdbTerminationPointAugmentation intf);
+ /**
+ * Gets the DHCP server port corresponding to a network.
+ *
+ * @param intf the intf
+ * @return the security group in port
+ */
+ public NeutronPort getDHCPServerPort(OvsdbTerminationPointAugmentation intf);
+
+ /**
+ * Is the port a compute port.
+ *
+ * @param intf the intf
+ * @return the security group in port
+ */
+ public boolean isComputePort(OvsdbTerminationPointAugmentation intf);
+ /**
+ * Is this the last port in the subnet to which interface belongs to.
+ *
+ * @param intf the intf
+ * @return the security group in port
+ */
+ public boolean isLastPortinSubnet(Node node, OvsdbTerminationPointAugmentation intf);
+
+ /**
+ * Is this the last port in the bridge to which interface belongs to.
+ *
+ * @param intf the intf
+ * @return the security group in port
+ */
+ public boolean isLastPortinBridge(Node node, OvsdbTerminationPointAugmentation intf);
+ /**
+ * Returns the list of ip adddress assigned to the interface.
+ *
+ * @param intf the intf
+ * @return the security group in port
+ */
+ public List<Neutron_IPs> getIpAddress(Node node, OvsdbTerminationPointAugmentation intf);
}
\ No newline at end of file
package org.opendaylight.ovsdb.openstack.netvirt.impl;
import java.util.List;
+
import org.opendaylight.neutron.spi.INeutronPortCRUD;
+import org.opendaylight.neutron.spi.INeutronSubnetCRUD;
import org.opendaylight.neutron.spi.NeutronPort;
import org.opendaylight.neutron.spi.NeutronSecurityGroup;
+import org.opendaylight.neutron.spi.NeutronSubnet;
+import org.opendaylight.neutron.spi.Neutron_IPs;
import org.opendaylight.ovsdb.openstack.netvirt.ConfigInterface;
import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNode;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
public class SecurityServicesImpl implements ConfigInterface, SecurityServicesManager {
static final Logger logger = LoggerFactory.getLogger(TenantNetworkManagerImpl.class);
private volatile INeutronPortCRUD neutronPortCache;
+ private volatile INeutronSubnetCRUD neutronSubnetCache;
private volatile Southbound southbound;
/**
}
}
+ @Override
+ public NeutronPort getDHCPServerPort(
+ OvsdbTerminationPointAugmentation terminationPointAugmentation) {
+ if (neutronPortCache == null) {
+ logger.error("getDHCPServerPort: neutron port is null");
+ return null;
+ }
+ logger.trace("getDHCPServerPort for {}",
+ terminationPointAugmentation.getName());
+ String neutronPortId = southbound.getInterfaceExternalIdsValue(
+ terminationPointAugmentation,
+ Constants.EXTERNAL_ID_INTERFACE_ID);
+ if (neutronPortId == null) {
+ return null;
+ }
+ NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
+ //Since all the fixed ip assigned to a port should be from the same network, first port is sufficient.
+ List<Neutron_IPs> fixedIps = neutronPort.getFixedIPs();
+ if(null==fixedIps || 0 == fixedIps.size() )
+ {
+ logger.error("getDHCPServerPort: No fixed ip is assigned");
+ return null;
+ }
+ String subnetUUID = fixedIps.iterator().next().getSubnetUUID();
+ NeutronSubnet neutronSubnet = neutronSubnetCache.getSubnet(subnetUUID);
+ List<NeutronPort> ports = neutronSubnet.getPortsInSubnet();
+ for (NeutronPort port : ports) {
+ if (port.getDeviceOwner().contains("dhcp")) {
+ return port;
+ }
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public boolean isComputePort(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
+ if (neutronPortCache == null) {
+ logger.error("neutron port is null");
+ return false;
+ }
+ logger.trace("isComputePort for {}", terminationPointAugmentation.getName());
+ String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
+ Constants.EXTERNAL_ID_INTERFACE_ID);
+ if (neutronPortId == null) {
+ return false;
+ }
+ NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
+ if (neutronPort == null) {
+ return false;
+ }
+ String deviceOwner = neutronPort.getDeviceOwner();
+ if (!deviceOwner.contains("compute")) {
+ logger.debug("isComputePort : Port {} is not a DHCP server port", neutronPortId,deviceOwner);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isLastPortinSubnet(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
+ if (neutronPortCache == null) {
+ logger.error("isLastPortinSubnet: neutron port is null");
+ return false;
+ }
+ logger.trace("isLastPortinSubnet: for {}", terminationPointAugmentation.getName());
+ String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
+ Constants.EXTERNAL_ID_INTERFACE_ID);
+ if (neutronPortId == null) {
+ return false;
+ }
+ NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
+ List<Neutron_IPs> neutronPortFixedIp = neutronPort.getFixedIPs();
+ if(null == neutronPortFixedIp || neutronPortFixedIp.isEmpty()) {
+ return false;
+ }
+ List<TerminationPoint> terminationPoints = node.getTerminationPoint();
+ if(terminationPoints != null && !terminationPoints.isEmpty()) {
+ for(TerminationPoint tp : terminationPoints) {
+ OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+ tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
+ if (ovsdbTerminationPointAugmentation != null && !ovsdbTerminationPointAugmentation.
+ getName().equals(Constants.INTEGRATION_BRIDGE)) {
+ String portId = southbound.getInterfaceExternalIdsValue(ovsdbTerminationPointAugmentation,
+ Constants.EXTERNAL_ID_INTERFACE_ID);
+ if(null!=portId) {
+ NeutronPort port = neutronPortCache.getPort(portId);
+ if(null!=port) {
+ if(!(port.getID().equals(neutronPort.getID())) && port.getDeviceOwner().contains("compute")) {
+ List<Neutron_IPs> portFixedIp = port.getFixedIPs();
+ if(null == portFixedIp || portFixedIp.isEmpty()) {
+ return false;
+ }
+ if(portFixedIp.iterator().next().getSubnetUUID().equals
+ (neutronPort.getFixedIPs().iterator().next().getSubnetUUID())) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isLastPortinBridge(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
+ logger.trace("isLastPortinBridge: for {}", terminationPointAugmentation.getName());
+ List<TerminationPoint> terminationPoints = node.getTerminationPoint();
+ if(terminationPoints != null && !terminationPoints.isEmpty()){
+ for(TerminationPoint tp : terminationPoints){
+ OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+ tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
+ if(null!=ovsdbTerminationPointAugmentation)
+ {
+ if(!(ovsdbTerminationPointAugmentation.getName().equals(Constants.INTEGRATION_BRIDGE))
+ && !(terminationPointAugmentation.getInterfaceUuid().equals
+ (ovsdbTerminationPointAugmentation.getInterfaceUuid()))) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public List<Neutron_IPs> getIpAddress(Node node,
+ OvsdbTerminationPointAugmentation terminationPointAugmentation) {
+ if (neutronPortCache == null) {
+ logger.error("getIpAddress: neutron port is null");
+ return null;
+ }
+ logger.trace("getIpAddress: for {}", terminationPointAugmentation.getName());
+ String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
+ Constants.EXTERNAL_ID_INTERFACE_ID);
+ if (neutronPortId == null) {
+ return null;
+ }
+ NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
+ List<Neutron_IPs> fixedIps = neutronPort.getFixedIPs();
+ return fixedIps;
+ }
+
@Override
public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
southbound =
if (impl instanceof INeutronPortCRUD) {
neutronPortCache = (INeutronPortCRUD)impl;
}
+ else if (impl instanceof INeutronSubnetCRUD) {
+ neutronSubnetCache = (INeutronSubnetCRUD) impl;
+ }
}
}
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.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
return matchBuilder;
}
+ /**
+ * Create a DHCP match with pot provided
+ *
+ * @param matchBuilder the match builder
+ * @param srcPort the source port
+ * @param dstPort the destination port
+ * @return the DHCP match
+ */
+ public static MatchBuilder createDHCPMatch(MatchBuilder matchBuilder, int srcPort, int dstPort) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ IpMatchBuilder ipmatch = new IpMatchBuilder();
+ ipmatch.setIpProtocol(UDP_SHORT);
+ matchBuilder.setIpMatch(ipmatch.build());
+
+ UdpMatchBuilder udpmatch = new UdpMatchBuilder();
+ udpmatch.setUdpSourcePort(new PortNumber(srcPort));
+ udpmatch.setUdpDestinationPort(new PortNumber(dstPort));
+ matchBuilder.setLayer4Match(udpmatch.build());
+
+ return matchBuilder;
+
+ }
+
+ /**
+ * Creates DHCP server packet match with DHCP mac address and port.
+ *
+ * @param matchBuilder the matchbuilder
+ * @param dhcpServerMac MAc address of the DHCP server of the subnet
+ * @param srcPort the source port
+ * @param dstPort the destination port
+ * @return the DHCP server match
+ */
+ public static MatchBuilder createDHCPServerMatch(MatchBuilder matchBuilder, String dhcpServerMac, int srcPort,
+ int dstPort) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder();
+ ethSourceBuilder.setAddress(new MacAddress(dhcpServerMac));
+ ethernetMatch.setEthernetSource(ethSourceBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ IpMatchBuilder ipmatch = new IpMatchBuilder();
+ ipmatch.setIpProtocol(UDP_SHORT);
+ matchBuilder.setIpMatch(ipmatch.build());
+
+ UdpMatchBuilder udpmatch = new UdpMatchBuilder();
+ udpmatch.setUdpSourcePort(new PortNumber(srcPort));
+ udpmatch.setUdpDestinationPort(new PortNumber(dstPort));
+ matchBuilder.setLayer4Match(udpmatch.build());
+
+ return matchBuilder;
+
+ }
+
+ /**
+ * @param matchBuilder MatchBuilder Object
+ * @param srcip String containing an IPv4 prefix
+ * @param srcMac The source macAddress
+ * @return matchBuilder Map Object with a match
+ */
+ public static MatchBuilder createSrcL3IPv4MatchWithMac(MatchBuilder matchBuilder, Ipv4Prefix srcip, MacAddress srcMac) {
+
+ Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder();
+ ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(srcip));
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ EthernetMatchBuilder eth = new EthernetMatchBuilder();
+ eth.setEthernetType(ethTypeBuilder.build());
+ eth.setEthernetSource(new EthernetSourceBuilder()
+ .setAddress(srcMac)
+ .build());
+
+ matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+ matchBuilder.setEthernetMatch(eth.build());
+ return matchBuilder;
+
+ }
+
public static class RegMatch {
final Class<? extends NxmNxReg> reg;
final Long value;