708eecb43d717e9bbf514d08fe8dcefda8f1fc0f
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / IcmpEchoResponderService.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
9
10 import com.google.common.collect.Lists;
11 import org.opendaylight.ovsdb.openstack.netvirt.api.*;
12 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
13 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
14 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
15 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
16 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
17 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
18 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
33 import org.osgi.framework.BundleContext;
34 import org.osgi.framework.ServiceReference;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import java.math.BigInteger;
39 import java.net.Inet6Address;
40 import java.net.InetAddress;
41 import java.util.List;
42
43 /**
44  * @author Josh Hershberg (jhershbe@redhat.com)
45  */
46 public class IcmpEchoResponderService extends AbstractServiceInstance implements IcmpEchoProvider, ConfigInterface {
47     private static final Logger LOG = LoggerFactory.getLogger(IcmpEchoResponderService.class);
48
49     public IcmpEchoResponderService() {
50         super(Service.ICMP_ECHO);
51     }
52
53     public IcmpEchoResponderService(Service service) {
54         super(service);
55     }
56
57     @Override
58     public Status programIcmpEchoEntry(Long dpid, String segmentationId, String macAddressStr, InetAddress ipAddress, Action action) {
59         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
60         MacAddress macAddress = new MacAddress(macAddressStr);
61
62         MatchBuilder matchBuilder = new MatchBuilder();
63         NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
64
65         // Instructions List Stores Individual Instructions
66         InstructionsBuilder isb = new InstructionsBuilder();
67         List<Instruction> instructions = Lists.newArrayList();
68         InstructionBuilder ib = new InstructionBuilder();
69         ApplyActionsBuilder aab = new ApplyActionsBuilder();
70         ActionBuilder ab = new ActionBuilder();
71         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList = Lists.newArrayList();
72
73         if (segmentationId != null) {
74             final Long inPort = MatchUtils.parseExplicitOFPort(segmentationId);
75             if (inPort != null) {
76                 MatchUtils.createInPortMatch(matchBuilder, dpid, inPort);
77             } else {
78                 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
79             }
80         }
81
82         if (ipAddress instanceof Inet6Address) {
83             // WORKAROUND: For now ipv6 is not supported
84             // TODO: implement ipv6 case
85             LOG.debug("ipv6 address case is not implemented yet. dpid {} segmentationId {} macAddressStr, ipAddress {} action {}",
86                     dpid, segmentationId, macAddressStr, ipAddress, action);
87             return new Status(StatusCode.NOTIMPLEMENTED);
88         }
89
90         // Match ICMP echo requests, type=8, code=0
91         MatchUtils.createICMPv4Match(matchBuilder, (short)8, (short)0);
92         MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress()));
93
94         // Move Eth Src to Eth Dst
95         ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
96         ab.setOrder(0);
97         ab.setKey(new ActionKey(0));
98         actionList.add(ab.build());
99
100         // Set Eth Src
101         ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
102         ab.setOrder(1);
103         ab.setKey(new ActionKey(1));
104         actionList.add(ab.build());
105
106         // Move Ip Src to Ip Dst
107         ab.setAction(ActionUtils.nxMoveIpSrcToIpDstAction());
108         ab.setOrder(2);
109         ab.setKey(new ActionKey(2));
110         actionList.add(ab.build());
111
112         // Set Ip Src
113         ab.setAction(ActionUtils.setNwSrcAction(new Ipv4Builder().setIpv4Address(
114                                     MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress())).build()));
115         ab.setOrder(3);
116         ab.setKey(new ActionKey(3));
117         actionList.add(ab.build());
118
119         // Set the ICMP type to 0 (echo reply)
120         ab.setAction(ActionUtils.setIcmpTypeAction((byte)0));
121         ab.setOrder(4);
122         ab.setKey(new ActionKey(4));
123         actionList.add(ab.build());
124
125         // Output of InPort
126         ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":INPORT")));
127         ab.setOrder(5);
128         ab.setKey(new ActionKey(5));
129         actionList.add(ab.build());
130
131         // Create Apply Actions Instruction
132         aab.setAction(actionList);
133         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
134         ib.setOrder(0);
135         ib.setKey(new InstructionKey(0));
136         instructions.add(ib.build());
137
138         FlowBuilder flowBuilder = new FlowBuilder();
139         String flowName = "IcmpEchoResponder_" + segmentationId + "_" + ipAddress.getHostAddress();
140         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
141         flowBuilder.setMatch(matchBuilder.build());
142         flowBuilder.setInstructions(isb.setInstruction(instructions).build());
143
144         if (action.equals(Action.ADD)) {
145             writeFlow(flowBuilder, nodeBuilder);
146         } else {
147             removeFlow(flowBuilder, nodeBuilder);
148         }
149
150         // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
151         return new Status(StatusCode.SUCCESS);
152     }
153
154     @Override
155     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
156         super.setDependencies(bundleContext.getServiceReference(IcmpEchoProvider.class.getName()), this);
157     }
158
159     @Override
160     public void setDependencies(Object impl) {}
161 }