2 * Copyright © 2016, 2017 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.ipv6service.utils;
11 import com.google.common.base.Optional;
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.List;
18 import java.util.concurrent.ExecutionException;
19 import javax.annotation.Nullable;
20 import javax.inject.Inject;
21 import javax.inject.Singleton;
22 import org.apache.commons.lang3.StringUtils;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.genius.infra.Datastore;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.ipv6util.api.Icmpv6Type;
30 import org.opendaylight.genius.ipv6util.api.Ipv6Constants;
31 import org.opendaylight.genius.ipv6util.api.Ipv6Util;
32 import org.opendaylight.genius.mdsalutil.ActionInfo;
33 import org.opendaylight.genius.mdsalutil.FlowEntity;
34 import org.opendaylight.genius.mdsalutil.InstructionInfo;
35 import org.opendaylight.genius.mdsalutil.MDSALUtil;
36 import org.opendaylight.genius.mdsalutil.MatchInfo;
37 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
38 import org.opendaylight.genius.mdsalutil.NwConstants;
39 import org.opendaylight.genius.mdsalutil.NwConstants.NxmOfFieldType;
40 import org.opendaylight.genius.mdsalutil.actions.ActionLearn;
41 import org.opendaylight.genius.mdsalutil.actions.ActionLearn.FlowMod;
42 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
43 import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
44 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
45 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
46 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
47 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
48 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
49 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6NdTarget;
50 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source;
51 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
52 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
53 import org.opendaylight.genius.utils.ServiceIndex;
54 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
55 import org.opendaylight.netvirt.ipv6service.VirtualSubnet;
56 import org.opendaylight.netvirt.ipv6service.api.IVirtualPort;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.config.rev181010.Ipv6serviceConfig;
76 import org.opendaylight.yangtools.yang.binding.DataObject;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
82 public class Ipv6ServiceUtils {
83 private static final Logger LOG = LoggerFactory.getLogger(Ipv6ServiceUtils.class);
84 public static final Ipv6Address ALL_NODES_MCAST_ADDR = newIpv6Address(Ipv6Constants.ALL_NODES_MCAST_ADDRESS);
85 public static final Ipv6Address UNSPECIFIED_ADDR = newIpv6Address("0:0:0:0:0:0:0:0");
88 private static Ipv6Address newIpv6Address(String ip) {
90 return Ipv6Address.getDefaultInstance(InetAddress.getByName(ip).getHostAddress());
91 } catch (UnknownHostException e) {
92 LOG.error("Ipv6ServiceUtils: Error instantiating ipv6 address", e);
97 private final DataBroker broker;
98 private final IMdsalApiManager mdsalUtil;
99 private final ManagedNewTransactionRunner txRunner;
100 private final Ipv6serviceConfig ipv6serviceConfig;
103 public Ipv6ServiceUtils(DataBroker broker, IMdsalApiManager mdsalUtil, Ipv6serviceConfig ipv6ServiceConfig) {
104 this.broker = broker;
105 this.mdsalUtil = mdsalUtil;
106 this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
107 this.ipv6serviceConfig = ipv6ServiceConfig;
111 * Retrieves the object from the datastore.
112 * @param datastoreType the data store type.
113 * @param path the wild card path.
114 * @return the required object.
116 public <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
117 try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
118 return tx.read(datastoreType, path).get();
119 } catch (InterruptedException | ExecutionException e) {
120 throw new RuntimeException(e);
125 * Retrieves the Interface from the datastore.
126 * @param interfaceName the interface name
127 * @return the interface.
130 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
131 .Interface getInterface(String interfaceName) {
132 return read(LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName)).orNull();
136 * Builds the interface identifier.
137 * @param interfaceName the interface name.
138 * @return the interface identifier.
140 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
141 .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
142 return InstanceIdentifier.builder(Interfaces.class)
144 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
145 .Interface.class, new InterfaceKey(interfaceName)).build();
149 * Build the interface state.
150 * @param interfaceName the interface name.
151 * @return the interface state.
153 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
154 .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
155 InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
156 InstanceIdentifier.builder(InterfacesState.class)
157 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
158 .state.Interface.class,
159 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
160 .rev140508.interfaces.state.InterfaceKey(interfaceName));
161 return idBuilder.build();
165 * Retrieves the interface state.
166 * @param interfaceName the interface name.
167 * @return the interface state.
170 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
171 .Interface getInterfaceStateFromOperDS(String interfaceName) {
172 return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, buildStateInterfaceId(interfaceName), broker).orNull();
175 private static List<MatchInfo> getIcmpv6RSMatch(Long elanTag) {
176 List<MatchInfo> matches = new ArrayList<>();
177 matches.add(MatchEthernetType.IPV6);
178 matches.add(MatchIpProtocol.ICMPV6);
179 matches.add(new MatchIcmpv6(Icmpv6Type.ROUTER_SOLICITATION.getValue(), (short) 0));
180 matches.add(new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
184 private List<MatchInfo> getIcmpv6NSMatch(Long elanTag, Ipv6Address ipv6Address) {
185 List<MatchInfo> matches = new ArrayList<>();
186 matches.add(MatchEthernetType.IPV6);
187 matches.add(MatchIpProtocol.ICMPV6);
188 matches.add(new MatchIcmpv6(Icmpv6Type.NEIGHBOR_SOLICITATION.getValue(), (short) 0));
189 matches.add(new MatchIpv6NdTarget(ipv6Address));
190 matches.add(new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
194 private List<MatchInfo> getIcmpv6NAMatch(Long elanTag) {
195 List<MatchInfo> matches = new ArrayList<>();
196 matches.add(MatchEthernetType.IPV6);
197 matches.add(MatchIpProtocol.ICMPV6);
198 matches.add(new MatchIcmpv6(Icmpv6Type.NEIGHBOR_ADVERTISEMENT.getValue(), (short) 0));
199 matches.add(new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
203 private static String getIPv6FlowRef(BigInteger dpId, Long elanTag, String flowType) {
204 return new StringBuffer().append(Ipv6ServiceConstants.FLOWID_PREFIX)
205 .append(dpId).append(Ipv6ServiceConstants.FLOWID_SEPARATOR)
206 .append(elanTag).append(Ipv6ServiceConstants.FLOWID_SEPARATOR)
207 .append(flowType).toString();
210 public void installIcmpv6NsPuntFlow(short tableId, BigInteger dpId, Long elanTag, Ipv6Address ipv6Address,
212 String flowId = getIPv6FlowRef(dpId, elanTag, Ipv6Util.getFormattedIpv6Address(ipv6Address));
214 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
215 LOG.trace("Removing IPv6 Neighbor Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
217 .addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
218 mdsalUtil.removeFlow(tx, dpId, flowId, tableId);
219 }), LOG, "Error while removing flow={}", flowId);
221 List<ActionInfo> actionsInfos = new ArrayList<>();
222 actionsInfos.add(new ActionPuntToController());
224 int ndPuntTimeout = ipv6serviceConfig.getNeighborDiscoveryPuntTimeout();
225 if (isNdPuntProtectionEnabled(ndPuntTimeout)) {
226 actionsInfos.add(getLearnActionForNsPuntProtection(ndPuntTimeout));
228 List<InstructionInfo> instructions = Arrays.asList(new InstructionApplyActions(actionsInfos));
229 List<MatchInfo> nsMatch = getIcmpv6NSMatch(elanTag, ipv6Address);
230 FlowEntity nsFlowEntity =
231 MDSALUtil.buildFlowEntity(dpId, tableId, flowId, Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY,
232 "IPv6NS", 0, 0, NwConstants.COOKIE_IPV6_TABLE, nsMatch, instructions);
234 LOG.trace("Installing IPv6 Neighbor Solicitation Flow DpId={}, elanTag={} ipv6Address={}", dpId, elanTag,
235 ipv6Address.getValue());
237 .addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
238 mdsalUtil.addFlow(tx, nsFlowEntity);
239 }), LOG, "Error while adding flow={}", nsFlowEntity);
243 private ActionLearn getLearnActionForNsPuntProtection(int ndPuntTimeout) {
244 List<FlowMod> flowMods = getFlowModsForIpv6PuntProtection(Icmpv6Type.NEIGHBOR_SOLICITATION);
245 flowMods.add(new ActionLearn.MatchFromField(NxmOfFieldType.NXM_NX_ND_TARGET.getType(),
246 NxmOfFieldType.NXM_NX_ND_TARGET.getType(), NxmOfFieldType.NXM_NX_ND_TARGET.getFlowModHeaderLenInt()));
248 return new ActionLearn(0, ndPuntTimeout, Ipv6ServiceConstants.NS_PUNT_PROTECTION_FLOW_PRIORITY,
249 NwConstants.COOKIE_IPV6_TABLE, 0, NwConstants.IPV6_TABLE, 0, 0, flowMods);
252 public void installIcmpv6RsPuntFlow(short tableId, BigInteger dpId, Long elanTag, int addOrRemove) {
253 if (dpId == null || dpId.equals(Ipv6ServiceConstants.INVALID_DPID)) {
256 String flowId = getIPv6FlowRef(dpId, elanTag, "IPv6RS");
257 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
258 LOG.trace("Removing IPv6 Router Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
260 .addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
261 mdsalUtil.removeFlow(tx, dpId, flowId, tableId);
262 }), LOG, "Error while removing flow={}", flowId);
264 List<ActionInfo> actionsInfos = new ArrayList<>();
265 // Punt to controller
266 actionsInfos.add(new ActionPuntToController());
268 int rdPuntTimeout = ipv6serviceConfig.getRouterDiscoveryPuntTimeout();
269 if (isRdPuntProtectionEnabled(rdPuntTimeout)) {
270 actionsInfos.add(getLearnActionForRsPuntProtection(rdPuntTimeout));
272 List<InstructionInfo> instructions = Arrays.asList(new InstructionApplyActions(actionsInfos));
273 List<MatchInfo> routerSolicitationMatch = getIcmpv6RSMatch(elanTag);
274 FlowEntity rsFlowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
275 flowId,Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY, "IPv6RS", 0, 0,
276 NwConstants.COOKIE_IPV6_TABLE, routerSolicitationMatch, instructions);
278 LOG.trace("Installing IPv6 Router Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
280 .addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
281 mdsalUtil.addFlow(tx, rsFlowEntity);
282 }), LOG, "Error while adding flow={}", rsFlowEntity);
286 private ActionLearn getLearnActionForRsPuntProtection(int rdPuntTimeout) {
287 return new ActionLearn(0, rdPuntTimeout, Ipv6ServiceConstants.RS_PUNT_PROTECTION_FLOW_PRIORITY,
288 NwConstants.COOKIE_IPV6_TABLE, 0, NwConstants.IPV6_TABLE, 0, 0,
289 getFlowModsForIpv6PuntProtection(Icmpv6Type.ROUTER_SOLICITATION));
292 private List<FlowMod> getFlowModsForIpv6PuntProtection(Icmpv6Type icmpv6Type) {
293 return new ArrayList<>(Arrays.asList(
294 new ActionLearn.MatchFromValue(NwConstants.ETHTYPE_IPV6, NxmOfFieldType.NXM_OF_ETH_TYPE.getType(),
295 NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLenInt()),
296 new ActionLearn.MatchFromValue(IPProtocols.IPV6ICMP.shortValue(),
297 NxmOfFieldType.NXM_OF_IP_PROTO.getType(),
298 NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLenInt()),
299 new ActionLearn.MatchFromValue(icmpv6Type.getValue(), NxmOfFieldType.NXM_OF_ICMPv6_TYPE.getType(),
300 NxmOfFieldType.NXM_OF_ICMPv6_TYPE.getFlowModHeaderLenInt()),
301 new ActionLearn.MatchFromField(NxmOfFieldType.NXM_OF_ICMPv6_CODE.getType(),
302 NxmOfFieldType.NXM_OF_ICMPv6_CODE.getType(),
303 NxmOfFieldType.NXM_OF_ICMPv6_CODE.getFlowModHeaderLenInt()),
304 new ActionLearn.MatchFromField(NxmOfFieldType.OXM_OF_METADATA.getType(),
305 MetaDataUtil.METADATA_LPORT_TAG_OFFSET, NxmOfFieldType.OXM_OF_METADATA.getType(),
306 MetaDataUtil.METADATA_LPORT_TAG_OFFSET, MetaDataUtil.METADATA_LPORT_TAG_BITLEN)));
309 private boolean isRdPuntProtectionEnabled(int rdPuntTimeout) {
310 return rdPuntTimeout != 0;
313 private boolean isNdPuntProtectionEnabled(int ndPuntTimeout) {
314 return ndPuntTimeout != 0;
317 public void installIcmpv6NaForwardFlow(short tableId, IVirtualPort vmPort, BigInteger dpId, Long elanTag,
319 List<MatchInfo> matches = getIcmpv6NAMatch(elanTag);
320 List<InstructionInfo> instructions = new ArrayList<>();
321 List<ActionInfo> actionsInfos = new ArrayList<>();
322 actionsInfos.add(new ActionNxResubmit(NwConstants.LPORT_DISPATCHER_TABLE));
323 instructions.add(new InstructionApplyActions(actionsInfos));
325 for (Ipv6Address ipv6Address : vmPort.getIpv6Addresses()) {
326 matches.add(new MatchIpv6Source(ipv6Address.getValue() + NwConstants.IPV6PREFIX));
327 String flowId = getIPv6FlowRef(dpId, elanTag,
328 vmPort.getIntfUUID().getValue() + Ipv6ServiceConstants.FLOWID_SEPARATOR + ipv6Address.getValue());
329 FlowEntity rsFlowEntity =
330 MDSALUtil.buildFlowEntity(dpId, tableId, flowId, Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY,
331 "IPv6NA", 0, 0, NwConstants.COOKIE_IPV6_TABLE, matches, instructions);
332 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
333 LOG.trace("Removing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}, ipv6Address {}", dpId,
334 elanTag, ipv6Address.getValue());
335 mdsalUtil.removeFlow(rsFlowEntity);
337 LOG.trace("Installing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}, ipv6Address {}", dpId,
338 elanTag, ipv6Address.getValue());
339 mdsalUtil.installFlow(rsFlowEntity);
344 public void installIcmpv6NaPuntFlow(short tableId, Ipv6Prefix ipv6Prefix, BigInteger dpId, Long elanTag,
346 List<MatchInfo> naMatch = getIcmpv6NAMatch(elanTag);
347 naMatch.add(new MatchIpv6Source(ipv6Prefix));
349 List<InstructionInfo> instructions = new ArrayList<>();
350 List<ActionInfo> actionsInfos = new ArrayList<>();
351 actionsInfos.add(new ActionPuntToController());
352 actionsInfos.add(new ActionNxResubmit(NwConstants.LPORT_DISPATCHER_TABLE));
353 instructions.add(new InstructionApplyActions(actionsInfos));
355 String flowId = getIPv6FlowRef(dpId, elanTag, "IPv6NA." + ipv6Prefix.getValue());
356 FlowEntity rsFlowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
357 flowId, Ipv6ServiceConstants.PUNT_NA_FLOW_PRIORITY,
358 "IPv6NA", 0, 0, NwConstants.COOKIE_IPV6_TABLE, naMatch, instructions);
359 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
360 LOG.trace("Removing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}", dpId, elanTag);
361 mdsalUtil.removeFlow(rsFlowEntity);
363 LOG.trace("Installing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}", dpId, elanTag);
364 mdsalUtil.installFlow(rsFlowEntity);
368 public BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
369 BigInteger cookie, List<Instruction> instructions) {
370 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie)
371 .setFlowPriority(flowPriority).setInstruction(instructions);
372 return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority))
373 .setServiceName(serviceName).setServicePriority(servicePriority)
374 .setServiceType(ServiceTypeFlowBased.class)
375 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
378 private InstanceIdentifier<BoundServices> buildServiceId(String interfaceName,
380 return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class,
381 new ServicesInfoKey(interfaceName, ServiceModeIngress.class))
382 .child(BoundServices.class, new BoundServicesKey(priority)).build();
385 public void bindIpv6Service(String interfaceName, Long elanTag, short tableId) {
386 int instructionKey = 0;
387 List<Instruction> instructions = new ArrayList<>();
388 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getElanTagMetadata(elanTag),
389 MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
390 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(tableId, ++instructionKey));
391 short serviceIndex = ServiceIndex.getIndex(NwConstants.IPV6_SERVICE_NAME, NwConstants.IPV6_SERVICE_INDEX);
394 getBoundServices(String.format("%s.%s", "ipv6", interfaceName),
395 serviceIndex, Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY,
396 NwConstants.COOKIE_IPV6_TABLE, instructions);
397 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
398 buildServiceId(interfaceName, serviceIndex), serviceInfo);
401 public void unbindIpv6Service(String interfaceName) {
402 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
403 buildServiceId(interfaceName, ServiceIndex.getIndex(NwConstants.IPV6_SERVICE_NAME,
404 NwConstants.IPV6_SERVICE_INDEX)));
408 public BigInteger getDpIdFromInterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
409 .interfaces.rev140508.interfaces.state.Interface interfaceState) {
410 BigInteger dpId = null;
411 List<String> ofportIds = interfaceState.getLowerLayerIf();
412 if (ofportIds != null && !ofportIds.isEmpty()) {
413 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
414 dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
419 public static long getRemoteBCGroup(long elanTag) {
420 return Ipv6ServiceConstants.ELAN_GID_MIN + elanTag % Ipv6ServiceConstants.ELAN_GID_MIN * 2;
423 public static boolean isVmPort(String deviceOwner) {
424 // FIXME: Currently for VM ports, Neutron is sending deviceOwner as empty instead of "compute:nova".
425 // return Ipv6ServiceConstants.DEVICE_OWNER_COMPUTE_NOVA.equalsIgnoreCase(deviceOwner);
426 return Ipv6ServiceConstants.DEVICE_OWNER_COMPUTE_NOVA.equalsIgnoreCase(deviceOwner)
427 || StringUtils.isEmpty(deviceOwner);
430 public static boolean isIpv6Subnet(VirtualSubnet subnet) {
431 if (subnet == null) {
434 return subnet.getIpVersion().equals(Ipv6ServiceConstants.IP_VERSION_V6) ? true : false;