Bug 4132 config ovs to respond to pings to router 24/32324/8
authorJosh <jhershbe@redhat.com>
Sun, 10 Jan 2016 11:13:01 +0000 (13:13 +0200)
committerFlavio Fernandes <ffernand@redhat.com>
Wed, 13 Jan 2016 02:52:09 +0000 (21:52 -0500)
Relies on https://git.opendaylight.org/gerrit/#/c/32135/
N.B. I added a unit test, IcmpEchoResponderServiceTest,
however it's currently skipped along with all the other
unit tests under services.

Patch set 8: Fix imports

Change-Id: If5d212c29acaf49d3cdd16cb9a02a63073202a88
Signed-off-by: Josh <jhershbe@redhat.com>
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/ConfigActivator.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/Service.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IcmpEchoResponderService.java [new file with mode: 0644]
openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstanceTest.java
openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/ArpResponderServiceTest.java
openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IcmpEchoResponderServiceTest.java [new file with mode: 0644]
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/ConfigActivator.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/IcmpEchoProvider.java [new file with mode: 0644]
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NeutronL3Adapter.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/ActionUtils.java

index 690fee05227767f054af06379c5c814ef7caa10d..c386920806a492cb983856859884b4dd51f03023 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Red Hat, Inc. and others. All rights reserved.
+ * Copyright (c) 2015, 2016 Red Hat, Inc. and others. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,11 +8,6 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.providers;
 
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
@@ -22,6 +17,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolver;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IcmpEchoProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
@@ -42,6 +38,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.ArpResponderService;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.ClassifierService;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.EgressAclService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.IcmpEchoResponderService;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.InboundNatService;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.IngressAclService;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.L2ForwardingService;
@@ -59,6 +56,11 @@ import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
 public class ConfigActivator implements BundleActivator {
     private static final Logger LOG = LoggerFactory.getLogger(ConfigActivator.class);
     private List<ServiceRegistration<?>> registrations = new ArrayList<>();
@@ -141,6 +143,10 @@ public class ConfigActivator implements BundleActivator {
                 gatewayMacResolverService, Service.GATEWAY_RESOLVER);
         getNotificationProviderService().registerNotificationListener(gatewayMacResolverService);
 
+        IcmpEchoResponderService icmpEchoResponderService = new IcmpEchoResponderService();
+        registerService(context, IcmpEchoProvider.class.getName(),
+                                            icmpEchoResponderService, Service.ICMP_ECHO);
+
         netvirtProvidersConfig.setDependencies(context, null);
         pipelineOrchestrator.setDependencies(context, null);
         outboundNatService.setDependencies(context, null);
@@ -156,6 +162,7 @@ public class ConfigActivator implements BundleActivator {
         classifierService.setDependencies(context, null);
         of13Provider.setDependencies(context, null);
         gatewayMacResolverService.setDependencies(context, null);
+        icmpEchoResponderService.setDependencies(context, null);
 
         @SuppressWarnings("unchecked")
         ServiceTracker networkingProviderManagerTracker = new ServiceTracker(context,
index 25177441218ed005b4c4788254738b7c1bb0608a..1ba5b82d9df2064ff89ce93fe31ac9909ff057dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
+ * Copyright (c) 2014 - 2016 Red Hat, Inc. and others. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -17,6 +17,7 @@ public enum Service {
     DIRECTOR ((short) 10, "Director"),
     SFC_CLASSIFIER ((short) 10, "SFC Classifier"),
     ARP_RESPONDER ((short) 20, "Distributed ARP Responder"),
+    ICMP_ECHO ((short) 20, "Distributed ICMP Echo Responder"),
     INBOUND_NAT ((short) 30, "DNAT for inbound floating-ip traffic"),
     EGRESS_ACL ((short) 40, "Egress Acces-control"),
     LOAD_BALANCER ((short) 50, "Distributed LBaaS"),
diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IcmpEchoResponderService.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IcmpEchoResponderService.java
new file mode 100644 (file)
index 0000000..708eecb
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
+
+import com.google.common.collect.Lists;
+import org.opendaylight.ovsdb.openstack.netvirt.api.*;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.List;
+
+/**
+ * @author Josh Hershberg (jhershbe@redhat.com)
+ */
+public class IcmpEchoResponderService extends AbstractServiceInstance implements IcmpEchoProvider, ConfigInterface {
+    private static final Logger LOG = LoggerFactory.getLogger(IcmpEchoResponderService.class);
+
+    public IcmpEchoResponderService() {
+        super(Service.ICMP_ECHO);
+    }
+
+    public IcmpEchoResponderService(Service service) {
+        super(service);
+    }
+
+    @Override
+    public Status programIcmpEchoEntry(Long dpid, String segmentationId, String macAddressStr, InetAddress ipAddress, Action action) {
+        String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+        MacAddress macAddress = new MacAddress(macAddressStr);
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
+
+        // Instructions List Stores Individual Instructions
+        InstructionsBuilder isb = new InstructionsBuilder();
+        List<Instruction> instructions = Lists.newArrayList();
+        InstructionBuilder ib = new InstructionBuilder();
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        ActionBuilder ab = new ActionBuilder();
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList = Lists.newArrayList();
+
+        if (segmentationId != null) {
+            final Long inPort = MatchUtils.parseExplicitOFPort(segmentationId);
+            if (inPort != null) {
+                MatchUtils.createInPortMatch(matchBuilder, dpid, inPort);
+            } else {
+                MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+            }
+        }
+
+        if (ipAddress instanceof Inet6Address) {
+            // WORKAROUND: For now ipv6 is not supported
+            // TODO: implement ipv6 case
+            LOG.debug("ipv6 address case is not implemented yet. dpid {} segmentationId {} macAddressStr, ipAddress {} action {}",
+                    dpid, segmentationId, macAddressStr, ipAddress, action);
+            return new Status(StatusCode.NOTIMPLEMENTED);
+        }
+
+        // Match ICMP echo requests, type=8, code=0
+        MatchUtils.createICMPv4Match(matchBuilder, (short)8, (short)0);
+        MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress()));
+
+        // Move Eth Src to Eth Dst
+        ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
+        actionList.add(ab.build());
+
+        // Set Eth Src
+        ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
+        ab.setOrder(1);
+        ab.setKey(new ActionKey(1));
+        actionList.add(ab.build());
+
+        // Move Ip Src to Ip Dst
+        ab.setAction(ActionUtils.nxMoveIpSrcToIpDstAction());
+        ab.setOrder(2);
+        ab.setKey(new ActionKey(2));
+        actionList.add(ab.build());
+
+        // Set Ip Src
+        ab.setAction(ActionUtils.setNwSrcAction(new Ipv4Builder().setIpv4Address(
+                                    MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress())).build()));
+        ab.setOrder(3);
+        ab.setKey(new ActionKey(3));
+        actionList.add(ab.build());
+
+        // Set the ICMP type to 0 (echo reply)
+        ab.setAction(ActionUtils.setIcmpTypeAction((byte)0));
+        ab.setOrder(4);
+        ab.setKey(new ActionKey(4));
+        actionList.add(ab.build());
+
+        // Output of InPort
+        ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":INPORT")));
+        ab.setOrder(5);
+        ab.setKey(new ActionKey(5));
+        actionList.add(ab.build());
+
+        // Create Apply Actions Instruction
+        aab.setAction(actionList);
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+        ib.setOrder(0);
+        ib.setKey(new InstructionKey(0));
+        instructions.add(ib.build());
+
+        FlowBuilder flowBuilder = new FlowBuilder();
+        String flowName = "IcmpEchoResponder_" + segmentationId + "_" + ipAddress.getHostAddress();
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
+        flowBuilder.setMatch(matchBuilder.build());
+        flowBuilder.setInstructions(isb.setInstruction(instructions).build());
+
+        if (action.equals(Action.ADD)) {
+            writeFlow(flowBuilder, nodeBuilder);
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
+
+        // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
+        return new Status(StatusCode.SUCCESS);
+    }
+
+    @Override
+    public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
+        super.setDependencies(bundleContext.getServiceReference(IcmpEchoProvider.class.getName()), this);
+    }
+
+    @Override
+    public void setDependencies(Object impl) {}
+}
index bf5bed238397861f365a337443ebe4e0ece7ea3f..b98e13a0a263596b81f9517bb73c464c7422fc12 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Inocybe and others.  All rights reserved.
+ * Copyright (c) 2015, 2016 Inocybe and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -32,7 +32,6 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.ovsdb.openstack.netvirt.NetvirtProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
@@ -45,7 +44,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.osgi.framework.ServiceReference;
 import org.powermock.api.mockito.PowerMockito;
index fbbd6e63d68b3da432b8dbd9763b4596835fed76..a36ae769e35af63ee129631a5cb3c511a10d342c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Inocybe and others.  All rights reserved.
+ * Copyright (c) 2015, 2016 Inocybe and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -17,7 +17,6 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.net.InetAddress;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -31,7 +30,6 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
-import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
@@ -39,7 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 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;
-import org.powermock.api.support.membermodification.MemberModifier;
 
 import com.google.common.util.concurrent.CheckedFuture;
 
diff --git a/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IcmpEchoResponderServiceTest.java b/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IcmpEchoResponderServiceTest.java
new file mode 100644 (file)
index 0000000..26509d0
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
+import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+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;
+
+import com.google.common.util.concurrent.CheckedFuture;
+
+import java.net.InetAddress;
+
+/**
+ * Unit test for {@link IcmpEchoResponderService}
+ */
+@RunWith(MockitoJUnitRunner.class)
+@SuppressWarnings("unchecked")
+public class IcmpEchoResponderServiceTest {
+    @InjectMocks private IcmpEchoResponderService icmpEchoResponderService = new IcmpEchoResponderService();
+
+    @Mock
+    private DataBroker dataBroker;
+
+    private static final String HOST_ADDRESS = "121.0.0.1";
+    private static final String MAC_ADDRESS = "87:1D:5E:02:40:B7";
+
+    @Test
+    public void testProgramIcmpEchoEntry() throws Exception {
+        icmpEchoResponderService.setService(Service.ARP_RESPONDER);
+
+        InetAddress ipAddress = mock(InetAddress.class);
+        when(ipAddress.getHostAddress()).thenReturn(HOST_ADDRESS);
+
+        WriteTransaction transaction = mock(WriteTransaction.class);
+        when(dataBroker.newWriteOnlyTransaction()).thenReturn(transaction);
+        CheckedFuture<Void, TransactionCommitFailedException> commitFuture = mock(CheckedFuture.class);
+        when(transaction.submit()).thenReturn(commitFuture);
+
+        NodeBuilder nodeBuilder = mock(NodeBuilder.class);
+        when(nodeBuilder.getKey()).thenReturn(mock(NodeKey.class));
+
+        FlowBuilder flowBuilder = mock(FlowBuilder.class);
+        when(flowBuilder.getKey()).thenReturn(mock(FlowKey.class));
+
+        // test Action.ADD
+        assertEquals("Error, did not return the expected StatusCode", new Status(StatusCode.SUCCESS), icmpEchoResponderService.programIcmpEchoEntry(Long.valueOf(12), "2", MAC_ADDRESS, ipAddress, Action.ADD));
+
+        verify(transaction, times(2)).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Node.class), anyBoolean());
+        verify(transaction, times(1)).submit();
+        verify(commitFuture, times(1)).get();
+
+        // test Action.DELETE
+        assertEquals("Error, did not return the expected StatusCode", new Status(StatusCode.SUCCESS), icmpEchoResponderService.programIcmpEchoEntry(Long.valueOf(12), "2", MAC_ADDRESS, ipAddress, Action.DELETE));
+
+        verify(transaction, times(1)).delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+        verify(commitFuture, times(2)).get(); // 1 + 1 above
+    }
+}
index 94b0f5a25f763072a17b98654a15190e70b5a101..32b44e8ffcbde3adb491ed118288ba5a685feb59 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Red Hat, Inc. and others. All rights reserved.
+ * Copyright (c) 2015, 2016 Red Hat, Inc. and others. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -16,9 +16,12 @@ import java.util.List;
 import org.apache.commons.lang3.tuple.Pair;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IcmpEchoProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.VlanConfigurationCache;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher;
@@ -39,8 +42,6 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityGroupCacheManger;
 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
-import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
-import org.opendaylight.ovsdb.openstack.netvirt.api.VlanConfigurationCache;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.BridgeConfigurationManagerImpl;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.ConfigurationServiceImpl;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.EventDispatcherImpl;
@@ -256,6 +257,7 @@ public class ConfigActivator implements BundleActivator {
         trackService(context, GatewayMacResolver.class, neutronL3Adapter);
         trackService(context, IngressAclProvider.class, securityServices);
         trackService(context, EgressAclProvider.class, securityServices);
+        trackService(context, IcmpEchoProvider.class, neutronL3Adapter);
 
         // We no longer need to track the services, avoid keeping references around
         servicesAndRegistrations.clear();
diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/IcmpEchoProvider.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/IcmpEchoProvider.java
new file mode 100644 (file)
index 0000000..4e429bf
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.ovsdb.openstack.netvirt.api;
+
+import java.net.InetAddress;
+
+/**
+ * @author Josh Hershberg (jhershbe@redhat.com)
+ */
+public interface IcmpEchoProvider {
+
+    Status programIcmpEchoEntry(Long dpid, String segmentationId,
+                                 String macAddress, InetAddress ipAddress, Action action);
+}
index 32969722f0af643d159ba14bca0dcc719163fbd9..84ad361b5bec0ead8932699b66ccb95db7752e90 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
+ * Copyright (c) 2014 - 2016 Red Hat, Inc. and others. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -22,6 +22,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher;
 import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolver;
 import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolverListener;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IcmpEchoProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.L3ForwardingProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
@@ -93,6 +94,7 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
     private volatile RoutingProvider routingProvider;
     private volatile GatewayMacResolver gatewayMacResolver;
     private volatile SecurityServicesManager securityServicesManager;
+    private volatile IcmpEchoProvider icmpEchoProvider;
 
     private class FloatIpData {
         // br-int of node where floating ip is associated with tenant port
@@ -1050,6 +1052,7 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
                 }
                 // Enable ARP responder by default, because router interface needs to be responded always.
                 programStaticArpStage1(dpid, destinationSegmentationId, macAddress, ipStr, actionForNode);
+                programIcmpEcho(dpid, destinationSegmentationId, macAddress, ipStr, actionForNode);
             }
 
             // Compute action to be programmed. In the case of rewrite exclusions, we must never program rules
@@ -1207,6 +1210,41 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
         return status;
     }
 
+    private boolean programIcmpEcho(Long dpid, String segOrOfPort,
+                                           String macAddress, String ipStr,
+                                           Action action) {
+        if (action == Action.DELETE ) {
+            LOG.trace("Deleting Flow : programIcmpEcho dpid {} segOrOfPort {} mac {} ip {} action {}",
+                    dpid, segOrOfPort, macAddress, ipStr, action);
+        }
+        if (action == Action.ADD) {
+            LOG.trace("Adding Flow : programIcmpEcho dpid {} segOrOfPort {} mac {} ip {} action {}",
+                    dpid, segOrOfPort, macAddress, ipStr, action);
+        }
+
+        Status status = new Status(StatusCode.UNSUPPORTED);
+        if (icmpEchoProvider != null){
+            try {
+                InetAddress inetAddress = InetAddress.getByName(ipStr);
+                status = icmpEchoProvider.programIcmpEchoEntry(dpid, segOrOfPort,
+                                                macAddress, inetAddress, action);
+            } catch (UnknownHostException e) {
+                status = new Status(StatusCode.BADREQUEST);
+            }
+        }
+
+        if (status.isSuccess()) {
+            LOG.debug("programIcmpEcho {} for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{}",
+                    icmpEchoProvider == null ? "skipped" : "programmed",
+                    macAddress, ipStr, dpid, segOrOfPort, action);
+        } else {
+            LOG.error("programIcmpEcho failed for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{} status:{}",
+                    macAddress, ipStr, dpid, segOrOfPort, action, status);
+        }
+
+        return status.isSuccess();
+    }
+
     private boolean programStaticArpStage1(Long dpid, String segOrOfPort,
                                            String macAddress, String ipStr,
                                            Action action) {
@@ -1215,7 +1253,7 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
                     dpid, segOrOfPort, macAddress, ipStr, action);
         }
         if (action == Action.ADD) {
-            LOG.trace("Adding Flow : programStaticArpStage1 dpid {} segOrOfPort {} mac {} ip {} action {} is already done",
+            LOG.trace("Adding Flow : programStaticArpStage1 dpid {} segOrOfPort {} mac {} ip {} action {}",
                     dpid, segOrOfPort, macAddress, ipStr, action);
         }
 
@@ -1522,6 +1560,7 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
                 (GatewayMacResolver) ServiceHelper.getGlobalInstance(GatewayMacResolver.class, this);
         securityServicesManager =
                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
+
         initL3AdapterMembers();
     }
 
@@ -1547,7 +1586,10 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
             l3ForwardingProvider = (L3ForwardingProvider)impl;
         }else if (impl instanceof GatewayMacResolver) {
             gatewayMacResolver = (GatewayMacResolver)impl;
+        }else if (impl instanceof IcmpEchoProvider) {
+            icmpEchoProvider = (IcmpEchoProvider)impl;
         }
+
         populateL3ForwardingCaches();
     }
 }
index 403e2e00aeaf2d041ca0c03f01a5bcd6d08a20c9..40411d103855c0962d1057bd3ffb82c29abf28e2 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.ovsdb.utils.mdsal.openflow;
 
+import com.google.common.net.InetAddresses;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
@@ -31,9 +32,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxHashFields;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxMpAlgorithm;
@@ -50,6 +51,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpSpaCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpTpaCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfIpDstCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionConntrackNodesNodeTableFlowApplyActionsCaseBuilder;
@@ -99,18 +101,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIpv4DstCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfArpSpaCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxHashFields;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxMpAlgorithm;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.multipath.grouping.NxMultipath;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.multipath.grouping.NxMultipathBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.resubmit.grouping.NxResubmit;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.resubmit.grouping.NxResubmitBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsi.grouping.NxSetNsi;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsi.grouping.NxSetNsiBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsp.grouping.NxSetNsp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsp.grouping.NxSetNspBuilder;
-
-import com.google.common.net.InetAddresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpSrcCaseBuilder;
 
 import java.math.BigInteger;
 
@@ -265,6 +256,14 @@ public final class ActionUtils {
         return nxLoadArpSpaAction(BigInteger.valueOf(ipl));
     }
 
+    public static Action setIcmpTypeAction(byte value) {
+        SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+        setFieldBuilder.setIcmpv4Match(new Icmpv4MatchBuilder().setIcmpv4Type((short)value).build());
+        return new SetFieldCaseBuilder()
+                .setSetField(setFieldBuilder.build())
+                .build();
+    }
+
     public static Action nxMoveRegAction(SrcChoice srcChoice,
                                          DstChoice dstChoice,
                                          int endOffset,
@@ -320,6 +319,12 @@ public final class ActionUtils {
                                new DstOfArpTpaCaseBuilder().setOfArpTpa(Boolean.TRUE).build());
     }
 
+    public static Action nxMoveIpSrcToIpDstAction() {
+        return nxMoveRegAction(new SrcOfIpSrcCaseBuilder().setOfIpSrc(Boolean.TRUE).build(),
+                               new DstOfIpDstCaseBuilder().setOfIpDst(Boolean.TRUE).build());
+    }
+
+
     public static Action nxOutputRegAction(SrcChoice srcChoice) {
         NxOutputReg r = new NxOutputRegBuilder()
             .setSrc(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.nx.output.reg.SrcBuilder()