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.inject.Inject;
20 import javax.inject.Singleton;
21 import org.apache.commons.lang3.StringUtils;
22 import org.eclipse.jdt.annotation.Nullable;
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.
129 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
130 .@Nullable Interface getInterface(String interfaceName) {
131 return read(LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName)).orNull();
135 * Builds the interface identifier.
136 * @param interfaceName the interface name.
137 * @return the interface identifier.
139 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
140 .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
141 return InstanceIdentifier.builder(Interfaces.class)
143 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
144 .Interface.class, new InterfaceKey(interfaceName)).build();
148 * Build the interface state.
149 * @param interfaceName the interface name.
150 * @return the interface state.
152 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
153 .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
154 InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
155 InstanceIdentifier.builder(InterfacesState.class)
156 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
157 .state.Interface.class,
158 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
159 .rev140508.interfaces.state.InterfaceKey(interfaceName));
160 return idBuilder.build();
164 * Retrieves the interface state.
165 * @param interfaceName the interface name.
166 * @return the interface state.
168 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
169 .@Nullable Interface getInterfaceStateFromOperDS(String interfaceName) {
170 return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, buildStateInterfaceId(interfaceName), broker).orNull();
173 private static List<MatchInfo> getIcmpv6RSMatch(Long elanTag) {
174 List<MatchInfo> matches = new ArrayList<>();
175 matches.add(MatchEthernetType.IPV6);
176 matches.add(MatchIpProtocol.ICMPV6);
177 matches.add(new MatchIcmpv6(Icmpv6Type.ROUTER_SOLICITATION.getValue(), (short) 0));
178 matches.add(new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
182 private List<MatchInfo> getIcmpv6NSMatch(Long elanTag, Ipv6Address ipv6Address) {
183 List<MatchInfo> matches = new ArrayList<>();
184 matches.add(MatchEthernetType.IPV6);
185 matches.add(MatchIpProtocol.ICMPV6);
186 matches.add(new MatchIcmpv6(Icmpv6Type.NEIGHBOR_SOLICITATION.getValue(), (short) 0));
187 matches.add(new MatchIpv6NdTarget(ipv6Address));
188 matches.add(new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
192 private List<MatchInfo> getIcmpv6NAMatch(Long elanTag) {
193 List<MatchInfo> matches = new ArrayList<>();
194 matches.add(MatchEthernetType.IPV6);
195 matches.add(MatchIpProtocol.ICMPV6);
196 matches.add(new MatchIcmpv6(Icmpv6Type.NEIGHBOR_ADVERTISEMENT.getValue(), (short) 0));
197 matches.add(new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
201 private static String getIPv6FlowRef(BigInteger dpId, Long elanTag, String flowType) {
202 return new StringBuilder().append(Ipv6ServiceConstants.FLOWID_PREFIX)
203 .append(dpId).append(Ipv6ServiceConstants.FLOWID_SEPARATOR)
204 .append(elanTag).append(Ipv6ServiceConstants.FLOWID_SEPARATOR)
205 .append(flowType).toString();
208 public void installIcmpv6NsPuntFlow(short tableId, BigInteger dpId, Long elanTag, Ipv6Address ipv6Address,
210 String flowId = getIPv6FlowRef(dpId, elanTag, Ipv6Util.getFormattedIpv6Address(ipv6Address));
212 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
213 LOG.trace("Removing IPv6 Neighbor Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
215 .addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
216 mdsalUtil.removeFlow(tx, dpId, flowId, tableId);
217 }), LOG, "Error while removing flow={}", flowId);
219 List<ActionInfo> actionsInfos = new ArrayList<>();
220 actionsInfos.add(new ActionPuntToController());
222 int ndPuntTimeout = ipv6serviceConfig.getNeighborDiscoveryPuntTimeout();
223 if (isNdPuntProtectionEnabled(ndPuntTimeout)) {
224 actionsInfos.add(getLearnActionForNsPuntProtection(ndPuntTimeout));
226 List<InstructionInfo> instructions = Arrays.asList(new InstructionApplyActions(actionsInfos));
227 List<MatchInfo> nsMatch = getIcmpv6NSMatch(elanTag, ipv6Address);
228 FlowEntity nsFlowEntity =
229 MDSALUtil.buildFlowEntity(dpId, tableId, flowId, Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY,
230 "IPv6NS", 0, 0, NwConstants.COOKIE_IPV6_TABLE, nsMatch, instructions);
232 LOG.trace("Installing IPv6 Neighbor Solicitation Flow DpId={}, elanTag={} ipv6Address={}", dpId, elanTag,
233 ipv6Address.getValue());
235 .addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
236 mdsalUtil.addFlow(tx, nsFlowEntity);
237 }), LOG, "Error while adding flow={}", nsFlowEntity);
241 private ActionLearn getLearnActionForNsPuntProtection(int ndPuntTimeout) {
242 List<FlowMod> flowMods = getFlowModsForIpv6PuntProtection(Icmpv6Type.NEIGHBOR_SOLICITATION);
243 flowMods.add(new ActionLearn.MatchFromField(NxmOfFieldType.NXM_NX_ND_TARGET.getType(),
244 NxmOfFieldType.NXM_NX_ND_TARGET.getType(), NxmOfFieldType.NXM_NX_ND_TARGET.getFlowModHeaderLenInt()));
246 return new ActionLearn(0, ndPuntTimeout, Ipv6ServiceConstants.NS_PUNT_PROTECTION_FLOW_PRIORITY,
247 NwConstants.COOKIE_IPV6_TABLE, 0, NwConstants.IPV6_TABLE, 0, 0, flowMods);
250 public void installIcmpv6RsPuntFlow(short tableId, BigInteger dpId, Long elanTag, int addOrRemove) {
251 if (dpId == null || dpId.equals(Ipv6ServiceConstants.INVALID_DPID)) {
254 String flowId = getIPv6FlowRef(dpId, elanTag, "IPv6RS");
255 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
256 LOG.trace("Removing IPv6 Router Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
258 .addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
259 mdsalUtil.removeFlow(tx, dpId, flowId, tableId);
260 }), LOG, "Error while removing flow={}", flowId);
262 List<ActionInfo> actionsInfos = new ArrayList<>();
263 // Punt to controller
264 actionsInfos.add(new ActionPuntToController());
266 int rdPuntTimeout = ipv6serviceConfig.getRouterDiscoveryPuntTimeout();
267 if (isRdPuntProtectionEnabled(rdPuntTimeout)) {
268 actionsInfos.add(getLearnActionForRsPuntProtection(rdPuntTimeout));
270 List<InstructionInfo> instructions = Arrays.asList(new InstructionApplyActions(actionsInfos));
271 List<MatchInfo> routerSolicitationMatch = getIcmpv6RSMatch(elanTag);
272 FlowEntity rsFlowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
273 flowId,Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY, "IPv6RS", 0, 0,
274 NwConstants.COOKIE_IPV6_TABLE, routerSolicitationMatch, instructions);
276 LOG.trace("Installing IPv6 Router Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
278 .addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
279 mdsalUtil.addFlow(tx, rsFlowEntity);
280 }), LOG, "Error while adding flow={}", rsFlowEntity);
284 private ActionLearn getLearnActionForRsPuntProtection(int rdPuntTimeout) {
285 return new ActionLearn(0, rdPuntTimeout, Ipv6ServiceConstants.RS_PUNT_PROTECTION_FLOW_PRIORITY,
286 NwConstants.COOKIE_IPV6_TABLE, 0, NwConstants.IPV6_TABLE, 0, 0,
287 getFlowModsForIpv6PuntProtection(Icmpv6Type.ROUTER_SOLICITATION));
290 private List<FlowMod> getFlowModsForIpv6PuntProtection(Icmpv6Type icmpv6Type) {
291 return new ArrayList<>(Arrays.asList(
292 new ActionLearn.MatchFromValue(NwConstants.ETHTYPE_IPV6, NxmOfFieldType.NXM_OF_ETH_TYPE.getType(),
293 NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLenInt()),
294 new ActionLearn.MatchFromValue(IPProtocols.IPV6ICMP.shortValue(),
295 NxmOfFieldType.NXM_OF_IP_PROTO.getType(),
296 NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLenInt()),
297 new ActionLearn.MatchFromValue(icmpv6Type.getValue(), NxmOfFieldType.NXM_OF_ICMPv6_TYPE.getType(),
298 NxmOfFieldType.NXM_OF_ICMPv6_TYPE.getFlowModHeaderLenInt()),
299 new ActionLearn.MatchFromField(NxmOfFieldType.NXM_OF_ICMPv6_CODE.getType(),
300 NxmOfFieldType.NXM_OF_ICMPv6_CODE.getType(),
301 NxmOfFieldType.NXM_OF_ICMPv6_CODE.getFlowModHeaderLenInt()),
302 new ActionLearn.MatchFromField(NxmOfFieldType.OXM_OF_METADATA.getType(),
303 MetaDataUtil.METADATA_LPORT_TAG_OFFSET, NxmOfFieldType.OXM_OF_METADATA.getType(),
304 MetaDataUtil.METADATA_LPORT_TAG_OFFSET, MetaDataUtil.METADATA_LPORT_TAG_BITLEN)));
307 private boolean isRdPuntProtectionEnabled(int rdPuntTimeout) {
308 return rdPuntTimeout != 0;
311 private boolean isNdPuntProtectionEnabled(int ndPuntTimeout) {
312 return ndPuntTimeout != 0;
315 public void installIcmpv6NaForwardFlow(short tableId, IVirtualPort vmPort, BigInteger dpId, Long elanTag,
317 List<MatchInfo> matches = getIcmpv6NAMatch(elanTag);
318 List<InstructionInfo> instructions = new ArrayList<>();
319 List<ActionInfo> actionsInfos = new ArrayList<>();
320 actionsInfos.add(new ActionNxResubmit(NwConstants.LPORT_DISPATCHER_TABLE));
321 instructions.add(new InstructionApplyActions(actionsInfos));
323 for (Ipv6Address ipv6Address : vmPort.getIpv6Addresses()) {
324 matches.add(new MatchIpv6Source(ipv6Address.getValue() + NwConstants.IPV6PREFIX));
325 String flowId = getIPv6FlowRef(dpId, elanTag,
326 vmPort.getIntfUUID().getValue() + Ipv6ServiceConstants.FLOWID_SEPARATOR + ipv6Address.getValue());
327 FlowEntity rsFlowEntity =
328 MDSALUtil.buildFlowEntity(dpId, tableId, flowId, Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY,
329 "IPv6NA", 0, 0, NwConstants.COOKIE_IPV6_TABLE, matches, instructions);
330 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
331 LOG.trace("Removing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}, ipv6Address {}", dpId,
332 elanTag, ipv6Address.getValue());
333 mdsalUtil.removeFlow(rsFlowEntity);
335 LOG.trace("Installing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}, ipv6Address {}", dpId,
336 elanTag, ipv6Address.getValue());
337 mdsalUtil.installFlow(rsFlowEntity);
342 public void installIcmpv6NaPuntFlow(short tableId, Ipv6Prefix ipv6Prefix, BigInteger dpId, Long elanTag,
344 List<MatchInfo> naMatch = getIcmpv6NAMatch(elanTag);
345 naMatch.add(new MatchIpv6Source(ipv6Prefix));
347 List<InstructionInfo> instructions = new ArrayList<>();
348 List<ActionInfo> actionsInfos = new ArrayList<>();
349 actionsInfos.add(new ActionPuntToController());
350 actionsInfos.add(new ActionNxResubmit(NwConstants.LPORT_DISPATCHER_TABLE));
351 instructions.add(new InstructionApplyActions(actionsInfos));
353 String flowId = getIPv6FlowRef(dpId, elanTag, "IPv6NA." + ipv6Prefix.getValue());
354 FlowEntity rsFlowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
355 flowId, Ipv6ServiceConstants.PUNT_NA_FLOW_PRIORITY,
356 "IPv6NA", 0, 0, NwConstants.COOKIE_IPV6_TABLE, naMatch, instructions);
357 if (addOrRemove == Ipv6ServiceConstants.DEL_FLOW) {
358 LOG.trace("Removing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}", dpId, elanTag);
359 mdsalUtil.removeFlow(rsFlowEntity);
361 LOG.trace("Installing IPv6 Neighbor Advertisement Flow DpId {}, elanTag {}", dpId, elanTag);
362 mdsalUtil.installFlow(rsFlowEntity);
366 public BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
367 BigInteger cookie, List<Instruction> instructions) {
368 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie)
369 .setFlowPriority(flowPriority).setInstruction(instructions);
370 return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority))
371 .setServiceName(serviceName).setServicePriority(servicePriority)
372 .setServiceType(ServiceTypeFlowBased.class)
373 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
376 private InstanceIdentifier<BoundServices> buildServiceId(String interfaceName,
378 return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class,
379 new ServicesInfoKey(interfaceName, ServiceModeIngress.class))
380 .child(BoundServices.class, new BoundServicesKey(priority)).build();
383 public void bindIpv6Service(String interfaceName, Long elanTag, short tableId) {
384 int instructionKey = 0;
385 List<Instruction> instructions = new ArrayList<>();
386 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getElanTagMetadata(elanTag),
387 MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
388 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(tableId, ++instructionKey));
389 short serviceIndex = ServiceIndex.getIndex(NwConstants.IPV6_SERVICE_NAME, NwConstants.IPV6_SERVICE_INDEX);
392 getBoundServices(String.format("%s.%s", "ipv6", interfaceName),
393 serviceIndex, Ipv6ServiceConstants.DEFAULT_FLOW_PRIORITY,
394 NwConstants.COOKIE_IPV6_TABLE, instructions);
395 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
396 buildServiceId(interfaceName, serviceIndex), serviceInfo);
399 public void unbindIpv6Service(String interfaceName) {
400 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
401 buildServiceId(interfaceName, ServiceIndex.getIndex(NwConstants.IPV6_SERVICE_NAME,
402 NwConstants.IPV6_SERVICE_INDEX)));
406 public BigInteger getDpIdFromInterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
407 .interfaces.rev140508.interfaces.state.Interface interfaceState) {
408 BigInteger dpId = null;
409 List<String> ofportIds = interfaceState.getLowerLayerIf();
410 if (ofportIds != null && !ofportIds.isEmpty()) {
411 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
412 dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
417 public static long getRemoteBCGroup(long elanTag) {
418 return Ipv6ServiceConstants.ELAN_GID_MIN + elanTag % Ipv6ServiceConstants.ELAN_GID_MIN * 2;
421 public static boolean isVmPort(String deviceOwner) {
422 // FIXME: Currently for VM ports, Neutron is sending deviceOwner as empty instead of "compute:nova".
423 // return Ipv6ServiceConstants.DEVICE_OWNER_COMPUTE_NOVA.equalsIgnoreCase(deviceOwner);
424 return Ipv6ServiceConstants.DEVICE_OWNER_COMPUTE_NOVA.equalsIgnoreCase(deviceOwner)
425 || StringUtils.isEmpty(deviceOwner);
428 public static boolean isIpv6Subnet(VirtualSubnet subnet) {
429 if (subnet == null) {
432 return subnet.getIpVersion().equals(Ipv6ServiceConstants.IP_VERSION_V6) ? true : false;