IPv6 support in Security Groups.
authorsridhargaddam <sgaddam@redhat.com>
Mon, 11 Jan 2016 16:10:49 +0000 (21:40 +0530)
committerSridhar Gaddam <sgaddam@redhat.com>
Wed, 20 Jan 2016 13:23:21 +0000 (18:53 +0530)
This patch implements IPv6 support for Security Groups in OVSDB
Net-virt.
Pending: Test cases will be added in a subsequent patch.

Change-Id: If692c9b205af87517d69cbcc9f8c1be4decc917e
Signed-off-by: Sridhar Gaddam <sgaddam@redhat.com>
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/EgressAclService.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IngressAclService.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java

index a3f1d0f5c0f6ea45a5970fbb2400873120ddc4fe..07aeb7df5064b5c4620a50c6c891f25581de01ea 100644 (file)
@@ -28,6 +28,7 @@ import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder;
 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.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
@@ -69,7 +70,10 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
     private volatile SecurityGroupCacheManger securityGroupCacheManger;
     private static final int DHCP_SOURCE_PORT = 67;
     private static final int DHCP_DESTINATION_PORT = 68;
+    private static final int DHCPV6_SOURCE_PORT = 547;
+    private static final int DHCPV6_DESTINATION_PORT = 546;
     private static final String HOST_MASK = "/32";
+    private static final String V6_HOST_MASK = "/128";
     private static final int PORT_RANGE_MIN = 1;
     private static final int PORT_RANGE_MAX = 65535;
 
@@ -109,9 +113,8 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                 continue;
             }
 
-            if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
-                    && portSecurityRule.getSecurityRuleDirection().equals("egress")) {
-                LOG.debug("programPortSecurityGroup: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
+            if (portSecurityRule.getSecurityRuleDirection().equals("egress")) {
+                LOG.debug("programPortSecurityGroup: Acl Rule matching IP and ingress is: {} ", portSecurityRule);
                 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
                     //Remote Security group is selected
                     List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
@@ -148,38 +151,13 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                                         Neutron_IPs vmIp, boolean write) {
         if (null == portSecurityRule.getSecurityRuleProtocol()) {
             /* TODO Rework on the priority values */
-            egressAclIPv4(dpid, segmentationId, attachedMac,
+            boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
+            egressAclIP(dpid, isIpv6, segmentationId, attachedMac,
                           write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
         } else {
             String ipaddress = null;
             if (null != vmIp) {
                 ipaddress = vmIp.getIpAddress();
-                try {
-                    InetAddress address = InetAddress.getByName(ipaddress);
-                    // TODO: remove this when ipv6 support is implemented
-                    if (address instanceof Inet6Address) {
-                        LOG.debug("Skipping ip address {}. IPv6 support is not yet implemented.", address);
-                        return;
-                    }
-                } catch (UnknownHostException e) {
-                    LOG.warn("Invalid ip address {}", ipaddress, e);
-                    return;
-                }
-            }
-
-            if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
-                String prefixStr = portSecurityRule.getSecurityRuleRemoteIpPrefix();
-                try {
-                    IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(prefixStr);
-                    // TODO: remove this when ipv6 support is implemented
-                    if (ipPrefix.getIpv6Prefix() != null) {
-                        LOG.debug("Skipping ip prefix {}. IPv6 support is not yet implemented.", ipPrefix);
-                        return;
-                    }
-                } catch (IllegalArgumentException e) {
-                    LOG.warn("Invalid ip prefix {}", prefixStr, e);
-                    return;
-                }
             }
 
             switch (portSecurityRule.getSecurityRuleProtocol()) {
@@ -196,6 +174,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                                Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
                   break;
               case MatchUtils.ICMP:
+              case MatchUtils.ICMPV6:
                   LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
                   egressAclIcmp(dpid, segmentationId, attachedMac,
                                 portSecurityRule, ipaddress,write,
@@ -217,7 +196,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                                                boolean write, Integer priority) {
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
+        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null);
 
         short proto = 0;
         try {
@@ -251,6 +230,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         // 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);
+            egressAclDhcpv6AllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
        // }
         if (isComputePort) {
             programArpRule(dpid, segmentationId, localPort, attachedMac, write);
@@ -260,6 +240,8 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
             // add rule to drop the DHCP server traffic originating from the vm.
             egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
                                                  Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
+            egressAclDhcpv6DropServerTrafficfromVm(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) {
                 try {
@@ -268,9 +250,10 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                         String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
                         egressAclAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix,
                                                              Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
-                    } else {
-                        LOG.debug("Skipping IPv6 address {}. IPv6 support is not yet implemented.",
-                                  srcAddress.getIpAddress());
+                    } else if (address instanceof Inet6Address) {
+                        String addressWithPrefix = srcAddress.getIpAddress() + V6_HOST_MASK;
+                        egressAclAllowTrafficFromVmIpV6MacPair(dpid, localPort, attachedMac, addressWithPrefix,
+                                                               Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
                     }
                 } catch(UnknownHostException e) {
                     LOG.warn("Invalid IP address {}", srcAddress.getIpAddress());
@@ -321,7 +304,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
          MatchBuilder matchBuilder = new MatchBuilder();
          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
          String flowName = "Egress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
-         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder, attachMac, null);
+         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder, attachMac, null);
          matchBuilder = MatchUtils.addCtState(matchBuilder,0x00,0X80);
          FlowBuilder flowBuilder = new FlowBuilder();
          flowBuilder.setMatch(matchBuilder.build());
@@ -409,19 +392,23 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      }
 
     /**
-     * Allows IPv4 packet egress from the src mac address.
+     * Allows IPv4/v6 packet egress from the src mac address.
      * @param dpidLong the dpid
      * @param segmentationId the segementation id
      * @param srcMac the src mac address
      * @param write add or remove
      * @param protoPortMatchPriority the protocol match priority.
      */
-    private void egressAclIPv4(Long dpidLong, String segmentationId, String srcMac,
+    private void egressAclIP(Long dpidLong, boolean isIpv6, String segmentationId, String srcMac,
                                boolean write, Integer protoPortMatchPriority ) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
+        if (isIpv6) {
+            matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
+        } else {
+            matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null);
+        }
         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
     }
 
@@ -443,7 +430,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         boolean portRange = false;
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
+        boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
+        if (isIpv6) {
+            matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
+        } else {
+            matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null);
+        }
 
         /* Custom TCP Match */
         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
@@ -463,13 +455,22 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         }
         if (null != dstAddress) {
             flowId = flowId + dstAddress;
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
-                                      MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
-
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
+                        MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+                        MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
+            }
         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
-                                      new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
+                        new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+                        new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+            }
         }
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
         if (portRange) {
@@ -489,8 +490,20 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         }
     }
 
+    private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
+            NeutronSecurityRule portSecurityRule, String dstAddress,
+            boolean write, Integer protoPortMatchPriority) {
+
+        boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
+        if (isIpv6) {
+            egressAclIcmpV6(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write, protoPortMatchPriority);
+        } else {
+            egressAclIcmpV4(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write, protoPortMatchPriority);
+        }
+    }
+
     /**
-     * Creates a egress match with src macaddress. If dest address is specified
+     * Creates a icmp egress match with src macaddress. If dest address is specified
      * destination specific match will be created. Otherwise a match with a
      * CIDR will be created.
      * @param dpidLong the dpid
@@ -501,13 +514,13 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      * @param write add or delete
      * @param protoPortMatchPriority the protocol match priority
      */
-    private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
-                               NeutronSecurityRule portSecurityRule, String dstAddress,
-                               boolean write, Integer protoPortMatchPriority) {
+    private void egressAclIcmpV4(Long dpidLong, String segmentationId, String srcMac,
+                                 NeutronSecurityRule portSecurityRule, String dstAddress,
+                                 boolean write, Integer protoPortMatchPriority) {
 
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
+        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null);
         /*Custom ICMP Match */
         if (portSecurityRule.getSecurityRulePortMin() != null &&
                              portSecurityRule.getSecurityRulePortMax() != null) {
@@ -537,6 +550,53 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
     }
 
+    /**
+     * Creates a icmpv6 egress match with src macaddress. If dest address is specified
+     * destination specific match will be created. Otherwise a match with a
+     * CIDR will be created.
+     * @param dpidLong the dpid
+     * @param segmentationId the segmentation id
+     * @param srcMac the source mac address.
+     * @param portSecurityRule the security rule in the SG
+     * @param dstAddress the source IP address
+     * @param write add or delete
+     * @param protoPortMatchPriority the protocol match priority
+     */
+    private void egressAclIcmpV6(Long dpidLong, String segmentationId, String srcMac,
+                                 NeutronSecurityRule portSecurityRule, String dstAddress,
+                                 boolean write, Integer protoPortMatchPriority) {
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
+        matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
+
+        /*Custom ICMP Match */
+        if (portSecurityRule.getSecurityRulePortMin() != null &&
+                             portSecurityRule.getSecurityRulePortMax() != null) {
+            flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
+                    + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
+            matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,
+                    portSecurityRule.getSecurityRulePortMin().shortValue(),
+                    portSecurityRule.getSecurityRulePortMax().shortValue());
+        } else {
+            /* All ICMP Match */ // We are getting from neutron NULL for both min and max
+            flowId = flowId + "all" + "_" ;
+            matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
+        }
+        if (null != dstAddress) {
+            flowId = flowId + dstAddress;
+            matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
+                    MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
+        } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
+            flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
+            matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
+                    new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+        }
+        flowId = flowId + "_Permit";
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
+    }
+
     /**
      * Creates a egress match with src macaddress. If dest address is specified
      * destination specific match will be created. Otherwise a match with a
@@ -555,7 +615,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         boolean portRange = false;
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
+        boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
+        if (isIpv6) {
+            matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);    
+        } else {
+            matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null);
+        }
 
         /* Custom UDP Match */
         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
@@ -575,13 +640,24 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         }
         if (null != dstAddress) {
             flowId = flowId + dstAddress;
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
-                                                        MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
+                        MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+                        MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
+            }
         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
-                                                        new Ipv4Prefix(portSecurityRule
-                                                                       .getSecurityRuleRemoteIpPrefix()));
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, null,
+                        new Ipv6Prefix(portSecurityRule
+                                       .getSecurityRuleRemoteIpPrefix()));
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
+                        new Ipv4Prefix(portSecurityRule
+                                       .getSecurityRuleRemoteIpPrefix()));
+            }
         }
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
         if (portRange) {
@@ -776,6 +852,22 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false);
     }
 
+    /**
+     * Adds flow to allow any DHCP IPv6 client traffic.
+     *
+     * @param dpidLong the dpid
+     * @param write whether to write or delete the flow
+     * @param priority the priority
+     */
+    private void egressAclDhcpv6AllowClientTrafficFromVm(Long dpidLong,
+                                                         boolean write, Integer priority) {
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        String flowName = "Egress_DHCPv6_Client"  + "_Permit_";
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_DESTINATION_PORT, DHCPV6_SOURCE_PORT);
+        syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false);
+    }
+
     /**
      * Adds rule to prevent DHCP spoofing by the vm attached to the port.
      *
@@ -795,6 +887,25 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, true, false);
     }
 
+    /**
+     * Adds rule to prevent DHCPv6 spoofing by the vm attached to the port.
+     *
+     * @param dpidLong the dpid
+     * @param localPort the local port
+     * @param write is write or delete
+     * @param priority  the priority
+     */
+    private void egressAclDhcpv6DropServerTrafficfromVm(Long dpidLong, long localPort,
+                                                        boolean write, Integer priority) {
+
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        String flowName = "Egress_DHCPv6_Server" + "_" + localPort + "_DROP_";
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
+        MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_SOURCE_PORT, DHCPV6_DESTINATION_PORT);
+        syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, true, false);
+    }
+
     /**
      * Adds rule to check legitimate ip/mac pair for each packet from the vm.
      *
@@ -817,6 +928,28 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false);
     }
 
+    /**
+     * 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 priority  the priority
+     * @param write is write or delete
+     */
+    private void egressAclAllowTrafficFromVmIpV6MacPair(Long dpidLong, long localPort,
+                                                        String attachedMac, String srcIp,
+                                                        Integer priority, boolean write) {
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        String flowName = "Egress_Allow_VM_IPv6_MAC" + "_" + localPort + attachedMac + "_Permit_";
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createSrcL3Ipv6MatchWithMac(matchBuilder, new Ipv6Prefix(srcIp),new MacAddress(attachedMac));
+        MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
+        LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
+        syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false);
+    }
+
     /**
      * Add or remove flow to the node.
      *
index e5d0a4c7d754c6a2e7ee92ad361d8c94e6c0c628..c437cea87791ad74321e0a313193d40b5b8d30e6 100644 (file)
@@ -28,6 +28,7 @@ import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder;
 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.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
@@ -105,9 +106,8 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
                 continue;
             }
 
-            if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
-                    && "ingress".equals(portSecurityRule.getSecurityRuleDirection())) {
-                LOG.debug("programPortSecurityGroup: Rule matching IPv4 and ingress is: {} ", portSecurityRule);
+            if ("ingress".equals(portSecurityRule.getSecurityRuleDirection())) {
+                LOG.debug("programPortSecurityGroup: Rule matching IP and ingress is: {} ", portSecurityRule);
                 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
                     //Remote Security group is selected
                     List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
@@ -142,39 +142,14 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
                                         long localPort, NeutronSecurityRule portSecurityRule,
                                         Neutron_IPs vmIp, boolean write) {
         if (null == portSecurityRule.getSecurityRuleProtocol()) {
-            ingressAclIPv4(dpid, segmentationId, attachedMac,
-                           write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+            boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
+            ingressAclIP(dpid, isIpv6, segmentationId, attachedMac,
+                         write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
         } else {
             String ipaddress = null;
             if (null != vmIp) {
                 ipaddress = vmIp.getIpAddress();
-                try {
-                    InetAddress address = InetAddress.getByName(ipaddress);
-                    // TODO: remove this when ipv6 support is implemented
-                    if (address instanceof Inet6Address) {
-                        LOG.debug("Skipping ip address {}. IPv6 support is not yet implemented.", address);
-                        return;
-                    }
-                } catch (UnknownHostException e) {
-                    LOG.warn("Invalid ip address {}", ipaddress, e);
-                    return;
-                }
-            }
-
-            if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
-                String ipPrefixStr = portSecurityRule.getSecurityRuleRemoteIpPrefix();
-                try {
-                    IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(ipPrefixStr);
-                    // TODO: remove this when ipv6 support is implemented
-                    if (ipPrefix.getIpv6Prefix() != null) {
-                        LOG.debug("Skipping ip prefix {}. IPv6 support is not yet implemented.", ipPrefix);
-                        return;
-                    }
-                } catch (IllegalArgumentException e) {
-                    LOG.warn("Invalid ip prefix {}", ipPrefixStr, e);
-                    return;
-                }
-            }
+            } 
 
             switch (portSecurityRule.getSecurityRuleProtocol()) {
               case MatchUtils.TCP:
@@ -188,6 +163,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
                                 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
                   break;
               case MatchUtils.ICMP:
+              case MatchUtils.ICMPV6:
                   LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
                   ingressAclIcmp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
                                  write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
@@ -208,7 +184,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
 
           MatchBuilder matchBuilder = new MatchBuilder();
           String flowId = "Ingress_Other_" + segmentationId + "_" + dstMac + "_";
-          matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
+          matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
           short proto = 0;
           try {
               Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
@@ -240,6 +216,8 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         if (isLastPortinSubnet && isComputePort ) {
             ingressAclDhcpAllowServerTraffic(dpid, segmentationId,dhcpMacAddress,
                                              write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
+            ingressAclDhcpv6AllowServerTraffic(dpid, segmentationId,dhcpMacAddress,
+                                               write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
         }
         if (isComputePort) {
             if (securityServicesManager.isConntrackEnabled()) {
@@ -289,7 +267,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         String flowName = "Ingress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
+        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac);
         matchBuilder = MatchUtils.addCtState(matchBuilder,0x00, 0x80);
         FlowBuilder flowBuilder = new FlowBuilder();
         flowBuilder.setMatch(matchBuilder.build());
@@ -327,7 +305,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         String flowName = "Ingress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
+        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac);
         matchBuilder = MatchUtils.addCtState(matchBuilder,0x82, 0x82);
         FlowBuilder flowBuilder = new FlowBuilder();
         flowBuilder.setMatch(matchBuilder.build());
@@ -355,7 +333,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         String flowName = "Ingress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
+        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac);
         matchBuilder = MatchUtils.addCtState(matchBuilder,0x01, 0x01);
         FlowBuilder flowBuilder = new FlowBuilder();
         flowBuilder.setMatch(matchBuilder.build());
@@ -387,22 +365,26 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
     }
 
     /**
-     * Allows IPv4 packet ingress to the destination mac address.
+     * Allows an IPv4/v6 packet ingress to the destination mac address.
      * @param dpidLong the dpid
      * @param segmentationId the segementation id
      * @param dstMac the destination mac address
      * @param write add or remove
      * @param protoPortMatchPriority the protocol match priority.
      */
-    private void ingressAclIPv4(Long dpidLong, String segmentationId, String dstMac,
-                                boolean write, Integer protoPortMatchPriority ) {
+    private void ingressAclIP(Long dpidLong, boolean isIpv6, String segmentationId, String dstMac,
+                              boolean write, Integer protoPortMatchPriority ) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Ingress_IP" + segmentationId + "_" + dstMac + "_Permit_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
+        if (isIpv6) {
+            matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
+        }else {
+            matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
+        }
         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
-
     }
+
     /**
      * Creates a ingress match to the dst macaddress. If src address is specified
      * source specific match will be created. Otherwise a match with a CIDR will
@@ -421,7 +403,12 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         boolean portRange = false;
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Ingress_TCP_" + segmentationId + "_" + dstMac + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
+        boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
+        if (isIpv6) {
+            matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
+        } else {
+            matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
+        }
 
         /* Custom TCP Match*/
         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
@@ -441,14 +428,24 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         }
         if (null != srcAddress) {
             flowId = flowId + srcAddress;
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
-                                                        MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
-
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
+                        MatchUtils.iPv6PrefixFromIPv6Address(srcAddress),null);
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
+                        MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
+            }
         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
-                                                        new Ipv4Prefix(portSecurityRule
-                                                                       .getSecurityRuleRemoteIpPrefix()),null);
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
+                        new Ipv6Prefix(portSecurityRule
+                                       .getSecurityRuleRemoteIpPrefix()),null);
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
+                        new Ipv4Prefix(portSecurityRule
+                                       .getSecurityRuleRemoteIpPrefix()),null);
+            }
         }
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
         if (portRange) {
@@ -484,9 +481,14 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
                                NeutronSecurityRule portSecurityRule, String srcAddress,
                                boolean write, Integer protoPortMatchPriority ) {
         boolean portRange = false;
+        boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Ingress_UDP_" + segmentationId + "_" + dstMac + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
+        if (isIpv6)  {
+            matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
+        }else {
+            matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
+        }
 
         /* Custom UDP Match */
         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
@@ -506,14 +508,24 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         }
         if (null != srcAddress) {
             flowId = flowId + srcAddress;
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
-                                                        MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
-
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
+                        MatchUtils.iPv6PrefixFromIPv6Address(srcAddress), null);
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
+                        MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
+            }
         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
-                                                        new Ipv4Prefix(portSecurityRule
-                                                                       .getSecurityRuleRemoteIpPrefix()),null);
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
+                        new Ipv6Prefix(portSecurityRule
+                                       .getSecurityRuleRemoteIpPrefix()),null);
+            } else {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
+                        new Ipv4Prefix(portSecurityRule
+                                       .getSecurityRuleRemoteIpPrefix()),null);
+            }
         }
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
         if (portRange) {
@@ -533,8 +545,20 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         }
     }
 
+    private void ingressAclIcmp(Long dpidLong, String segmentationId, String dstMac,
+            NeutronSecurityRule portSecurityRule, String srcAddress,
+            boolean write, Integer protoPortMatchPriority) {
+
+        boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
+        if (isIpv6) {
+            ingressAclIcmpV6(dpidLong, segmentationId, dstMac, portSecurityRule, srcAddress, write, protoPortMatchPriority);
+        } else {
+            ingressAclIcmpV4(dpidLong, segmentationId, dstMac, portSecurityRule, srcAddress, write, protoPortMatchPriority);
+        }
+    }
+
     /**
-     * Creates a ingress match to the dst macaddress. If src address is specified
+     * Creates a ingress icmp match to the dst macaddress. If src address is specified
      * source specific match will be created. Otherwise a match with a CIDR will
      * be created.
      * @param dpidLong the dpid
@@ -545,13 +569,13 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
      * @param write add or delete
      * @param protoPortMatchPriority the protocol match priority
      */
-    private void ingressAclIcmp(Long dpidLong, String segmentationId, String dstMac,
-                                NeutronSecurityRule portSecurityRule, String srcAddress,
-                                boolean write, Integer protoPortMatchPriority) {
+    private void ingressAclIcmpV4(Long dpidLong, String segmentationId, String dstMac,
+                                  NeutronSecurityRule portSecurityRule, String srcAddress,
+                                  boolean write, Integer protoPortMatchPriority) {
 
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_";
-        matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
+        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
 
         /* Custom ICMP Match */
         if (portSecurityRule.getSecurityRulePortMin() != null &&
@@ -569,7 +593,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         if (null != srcAddress) {
             flowId = flowId + srcAddress;
             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
-                                                        MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
+                   MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
             if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
@@ -582,6 +606,54 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
     }
 
+    /**
+     * Creates a ingress icmpv6 match to the dst macaddress. If src address is specified
+     * source specific match will be created. Otherwise a match with a CIDR will
+     * be created.
+     * @param dpidLong the dpid
+     * @param segmentationId the segmentation id
+     * @param dstMac the destination mac address.
+     * @param portSecurityRule the security rule in the SG
+     * @param srcAddress the destination IP address
+     * @param write add or delete
+     * @param protoPortMatchPriority the protocol match priority
+     */
+    private void ingressAclIcmpV6(Long dpidLong, String segmentationId, String dstMac,
+                                  NeutronSecurityRule portSecurityRule, String srcAddress,
+                                  boolean write, Integer protoPortMatchPriority) {
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_";
+        matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
+
+        /* Custom ICMP Match */
+        if (portSecurityRule.getSecurityRulePortMin() != null &&
+                portSecurityRule.getSecurityRulePortMax() != null) {
+            flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
+                    + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
+            matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,
+                    portSecurityRule.getSecurityRulePortMin().shortValue(),
+                    portSecurityRule.getSecurityRulePortMax().shortValue());
+        } else {
+            /* All ICMP Match */
+            flowId = flowId + "all" + "_";
+            matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
+        }
+        if (null != srcAddress) {
+            flowId = flowId + srcAddress;
+            matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
+                    MatchUtils.iPv6PrefixFromIPv6Address(srcAddress), null);
+        } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
+            flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
+            matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
+                    new Ipv6Prefix(portSecurityRule
+                                   .getSecurityRuleRemoteIpPrefix()),null);
+        }
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        flowId = flowId + "_Permit";
+        syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
+    }
+
 
     public void ingressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
                                  Integer securityRulePortMin, Integer protoPortMatchPriority) {
@@ -854,6 +926,25 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
     }
 
+    /**
+     * Add rule to ensure only DHCPv6 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 ingressAclDhcpv6AllowServerTraffic(Long dpidLong, String segmentationId, String dhcpMacAddress,
+                                                    boolean write, Integer protoPortMatchPriority) {
+
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createDhcpv6ServerMatch(matchBuilder, dhcpMacAddress, 547, 546).build();
+        String flowId = "Ingress_DHCPv6_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_";
+        syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
+    }
+
     /**
      * Add or remove flow to the node.
      *
index 7078486a92553a1d5a018a1fdc33c61cfc00c3c9..cbb73c0d2097ba3e9c34a0c17e2fb096916e629a 100644 (file)
@@ -15,6 +15,7 @@ import java.util.List;
 import java.util.Map;
 
 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.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
@@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
 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.Icmpv6MatchBuilder;
 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.MetadataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagMatchBuilder;
@@ -34,6 +36,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.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._3.match.Ipv6MatchBuilder;
 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;
@@ -97,6 +100,7 @@ public class MatchUtils {
     public static final String UDP = "udp";
     private static final int TCP_SYN = 0x0002;
     public static final String ICMP = "icmp";
+    public static final String ICMPV6 = "icmpv6";
     public static final short ALL_ICMP = -1;
 
     /**
@@ -247,6 +251,32 @@ public class MatchUtils {
         return matchBuilder;
     }
 
+    /**
+     * Match ICMPv6 code and type
+     *
+     * @param matchBuilder MatchBuilder Object
+     * @param type         short representing an ICMP type
+     * @param code         short representing an ICMP code
+     * @return matchBuilder Map MatchBuilder Object with a match
+     */
+    public static MatchBuilder createICMPv6Match(MatchBuilder matchBuilder, short type, short code) {
+
+        // Build the IPv6 Match required per OVS Syntax
+        IpMatchBuilder ipmatch = new IpMatchBuilder();
+        ipmatch.setIpProtocol((short) 58);
+        matchBuilder.setIpMatch(ipmatch.build());
+
+        // Build the ICMPv6 Match
+        Icmpv6MatchBuilder icmpv6match = new Icmpv6MatchBuilder();
+        if (type != ALL_ICMP || code != ALL_ICMP) {
+            icmpv6match.setIcmpv6Type(type);
+            icmpv6match.setIcmpv6Code(code);
+        }
+        matchBuilder.setIcmpv6Match(icmpv6match.build());
+
+        return matchBuilder;
+    }
+
     /**
      * @param matchBuilder MatchBuilder Object without a match yet
      * @param dstip        String containing an IPv4 prefix
@@ -442,6 +472,35 @@ public class MatchUtils {
         return matchBuilder;
     }
 
+    /**
+     * Create  TCP Port Match
+     *
+     * @param matchBuilder MatchBuilder Object without a match yet
+     * @param ipProtocol   Integer representing the IP protocol
+     * @return matchBuilder Map MatchBuilder Object with a match
+     */
+    public static MatchBuilder createIpv6ProtocolMatch(MatchBuilder matchBuilder, short ipProtocol) {
+
+        EthernetMatchBuilder ethType = new EthernetMatchBuilder();
+        EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+        ethTypeBuilder.setType(new EtherType(0x86DDL));
+        ethType.setEthernetType(ethTypeBuilder.build());
+        matchBuilder.setEthernetMatch(ethType.build());
+
+        IpMatchBuilder ipMmatch = new IpMatchBuilder();
+        if (ipProtocol == TCP_SHORT) {
+            ipMmatch.setIpProtocol(TCP_SHORT);
+        }
+        else if (ipProtocol == UDP_SHORT) {
+            ipMmatch.setIpProtocol(UDP_SHORT);
+        }
+        else if (ipProtocol == ICMP_SHORT) {
+            ipMmatch.setIpProtocol(ICMP_SHORT);
+        }
+        matchBuilder.setIpMatch(ipMmatch.build());
+        return matchBuilder;
+    }
+
     /**
      * Create tcp syn with proto match.
      *
@@ -922,7 +981,7 @@ public class MatchUtils {
     }
 
     /**
-     * Create a DHCP match with pot provided.
+     * Create a DHCP match with port provided.
      *
      * @param matchBuilder the match builder
      * @param srcPort the source port
@@ -951,6 +1010,36 @@ public class MatchUtils {
 
     }
 
+    /**
+     * Create a DHCP match with port provided.
+     *
+     * @param matchBuilder the match builder
+     * @param srcPort the source port
+     * @param dstPort the destination port
+     * @return the DHCP match
+     */
+    public static MatchBuilder createDhcpv6Match(MatchBuilder matchBuilder,
+                                                 int srcPort, int dstPort) {
+
+        EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+        EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+        ethTypeBuilder.setType(new EtherType(0x86DDL));
+        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.
      *
@@ -987,6 +1076,42 @@ public class MatchUtils {
 
     }
 
+    /**
+     * Creates DHCPv6 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 createDhcpv6ServerMatch(MatchBuilder matchBuilder, String dhcpServerMac, int srcPort,
+            int dstPort) {
+
+        EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+        EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+        ethTypeBuilder.setType(new EtherType(0x86DDL));
+        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;
+
+    }
+
     /**
      * Creates a Match with src ip address mac address set.
      * @param matchBuilder MatchBuilder Object
@@ -1012,6 +1137,31 @@ public class MatchUtils {
 
     }
 
+    /**
+     * Creates a Match with src ip address mac address set.
+     * @param matchBuilder MatchBuilder Object
+     * @param srcip String containing an IPv6 prefix
+     * @param srcMac The source macAddress
+     * @return matchBuilder Map Object with a match
+     */
+    public static MatchBuilder createSrcL3Ipv6MatchWithMac(MatchBuilder matchBuilder, Ipv6Prefix srcip, MacAddress srcMac) {
+
+        Ipv6MatchBuilder ipv6MatchBuilder = new Ipv6MatchBuilder();
+        ipv6MatchBuilder.setIpv6Source(new Ipv6Prefix(srcip));
+        EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+        ethTypeBuilder.setType(new EtherType(0x86DDL));
+        EthernetMatchBuilder eth = new EthernetMatchBuilder();
+        eth.setEthernetType(ethTypeBuilder.build());
+        eth.setEthernetSource(new EthernetSourceBuilder()
+                .setAddress(srcMac)
+                .build());
+
+        matchBuilder.setLayer3Match(ipv6MatchBuilder.build());
+        matchBuilder.setEthernetMatch(eth.build());
+        return matchBuilder;
+
+    }
+
     /**
      * Creates a ether net match with ether type set to 0x0800L.
      * @param matchBuilder MatchBuilder Object
@@ -1019,7 +1169,7 @@ public class MatchUtils {
      * @param dstMac The destination mac address
      * @return matchBuilder Map Object with a match
      */
-    public static MatchBuilder createEtherMatchWithType(MatchBuilder matchBuilder,String srcMac, String dstMac)
+    public static MatchBuilder createV4EtherMatchWithType(MatchBuilder matchBuilder,String srcMac, String dstMac)
     {
         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
         ethTypeBuilder.setType(new EtherType(0x0800L));
@@ -1036,6 +1186,32 @@ public class MatchUtils {
         matchBuilder.setEthernetMatch(eth.build());
         return matchBuilder;
     }
+
+    /**
+     * Creates a ether net match with ether type set to 0x86DDL.
+     * @param matchBuilder MatchBuilder Object
+     * @param srcMac The source macAddress
+     * @param dstMac The destination mac address
+     * @return matchBuilder Map Object with a match
+     */
+    public static MatchBuilder createV6EtherMatchWithType(MatchBuilder matchBuilder,String srcMac, String dstMac)
+    {
+        EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+        ethTypeBuilder.setType(new EtherType(0x86DDL));
+        EthernetMatchBuilder eth = new EthernetMatchBuilder();
+        eth.setEthernetType(ethTypeBuilder.build());
+        if (null != srcMac) {
+            eth.setEthernetSource(new EthernetSourceBuilder()
+            .setAddress(new MacAddress(srcMac)).build());
+        }
+        if (null != dstMac) {
+            eth.setEthernetDestination(new EthernetDestinationBuilder()
+                           .setAddress(new MacAddress(dstMac)).build());
+        }
+        matchBuilder.setEthernetMatch(eth.build());
+        return matchBuilder;
+    }
+
     /**
      * Adds remote Ip prefix to existing match.
      * @param matchBuilder The match builder
@@ -1056,6 +1232,28 @@ public class MatchUtils {
 
         return matchBuilder;
     }
+
+    /**
+     * Adds remote Ipv6 prefix to existing match.
+     * @param matchBuilder The match builder
+     * @param sourceIpPrefix The source IP prefix
+     * @param destIpPrefix The destination IP prefix
+     * @return matchBuilder Map Object with a match
+     */
+    public static MatchBuilder addRemoteIpv6Prefix(MatchBuilder matchBuilder,
+                                                   Ipv6Prefix sourceIpPrefix,Ipv6Prefix destIpPrefix) {
+        Ipv6MatchBuilder ipv6match = new Ipv6MatchBuilder();
+        if (null != sourceIpPrefix) {
+            ipv6match.setIpv6Source(sourceIpPrefix);
+        }
+        if (null != destIpPrefix) {
+            ipv6match.setIpv6Destination(destIpPrefix);
+        }
+        matchBuilder.setLayer3Match(ipv6match.build());
+
+        return matchBuilder;
+    }
+
     /**
      * Add a layer4 match to an existing match
      *
@@ -1351,6 +1549,16 @@ public class MatchUtils {
         return new Ipv4Prefix(ipv4AddressString + "/32");
     }
 
+    /**
+     * Create ipv6 prefix from ipv6 address, by appending /128 mask
+     *
+     * @param ipv6AddressString the ip address, in string format
+     * @return Ipv6Prefix with ipv6Address and /128 mask
+     */
+    public static Ipv6Prefix iPv6PrefixFromIPv6Address(String ipv6AddressString) {
+        return new Ipv6Prefix(ipv6AddressString + "/128");
+    }
+
     /**
      * Converts port range into a set of masked port ranges.
      *