2 * Copyright © 2015 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.openstack.netvirt.sfc.workaround;
11 import com.google.common.base.Preconditions;
12 import java.util.List;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
15 import org.opendaylight.netvirt.openstack.netvirt.api.NodeCacheManager;
16 import org.opendaylight.netvirt.openstack.netvirt.api.OvsdbTables;
17 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
18 import org.opendaylight.netvirt.openstack.netvirt.sfc.INetvirtSfcOF13Provider;
19 import org.opendaylight.netvirt.openstack.netvirt.sfc.ISfcClassifierService;
20 import org.opendaylight.netvirt.openstack.netvirt.sfc.NshUtils;
21 import org.opendaylight.netvirt.openstack.netvirt.sfc.SfcUtils;
22 import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
23 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
24 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
25 import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
26 import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
27 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
28 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
29 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop;
31 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
32 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
33 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
34 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
35 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
48 import org.osgi.framework.ServiceReference;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider {
53 private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcWorkaroundOF13Provider.class);
54 private volatile NodeCacheManager nodeCacheManager;
55 private volatile Southbound southbound;
56 private volatile ISfcClassifierService sfcClassifierService;
57 private static final short SFC_TABLE = 150;
58 private MdsalUtils mdsalUtils;
59 private SfcUtils sfcUtils;
60 private DataBroker dataBroker;
61 private static final String VXGPE = "vxgpe";
62 public static final String TUNNEL_ENDPOINT_KEY = "local_ip";
63 private Boolean addSfFlows;
65 public NetvirtSfcWorkaroundOF13Provider(final DataBroker dataBroker, MdsalUtils mdsalUtils,
66 SfcUtils sfcUtils, Boolean addSfFlows) {
67 Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
68 Preconditions.checkNotNull(mdsalUtils, "Input mdsalUtils cannot be NULL!");
69 Preconditions.checkNotNull(sfcUtils, "Input sfcUtils cannot be NULL!");
71 this.dataBroker = dataBroker;
72 this.mdsalUtils = mdsalUtils;
73 this.sfcUtils = sfcUtils;
74 this.addSfFlows = addSfFlows;
77 public void setSfcClassifierService(ISfcClassifierService sfcClassifierService) {
78 this.sfcClassifierService = sfcClassifierService;
82 public void addClassifierRules(Bridge bridge, Acl acl) {
87 public void addClassifierRules(Bridges bridges, Acl acl) {
88 Preconditions.checkNotNull(bridges, "Input bridges cannot be NULL!");
89 Preconditions.checkNotNull(acl, "Input acl cannot be NULL!");
93 public void removeClassifierRules(Sff sff, Acl acl) {
98 public void addClassifierRules(Acl acl) {
99 for (Ace ace : acl.getAccessListEntries().getAce()) {
100 processAclEntry(ace);
105 public void removeClassifierRules(Acl acl) {
106 for (Ace ace : acl.getAccessListEntries().getAce()) {
107 RenderedServicePath rsp = getRenderedServicePath(ace);
109 LOG.warn("Failed to get renderedServicePatch for entry: {}", ace);
112 sfcClassifierService.clearFlows(dataBroker, rsp.getName().getValue());
117 public void removeRsp(RenderedServicePath change) {
118 sfcClassifierService.clearFlows(dataBroker, change.getName().getValue());
122 public void addRsp(RenderedServicePath change) {
123 handleRenderedServicePath(change);
127 public void updateRsp(RenderedServicePath change) {
128 LOG.info("updateRsp not implemented yet");
131 private void processAclEntry(Ace entry) {
132 Matches matches = entry.getMatches();
133 Preconditions.checkNotNull(matches, "ACL Entry cannot be null!");
135 RenderedServicePath rsp = getRenderedServicePath(entry);
137 LOG.warn("Failed to get renderedServicePatch for entry: {}", entry);
141 handleRenderedServicePath(rsp, entry);
144 private void handleRenderedServicePath(RenderedServicePath rsp) {
145 LOG.info("handleRenderedServicePath: RSP: {}", rsp);
146 Ace entry = getAceFromRenderedServicePath(rsp);
148 LOG.warn("handleRenderedServicePath: failed to get acl entry");
152 handleRenderedServicePath(rsp, entry);
155 private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
156 LOG.info("handleRenderedServicePath: RSP: {}, Ace: {}", rsp, entry);
158 Matches matches = entry.getMatches();
159 if (matches == null) {
160 LOG.warn("processAclEntry: matches not found");
164 List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
165 if (pathHopList.isEmpty()) {
166 LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
169 LOG.info("handleRenderedServicePath: pathHopList: {}", pathHopList);
171 RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
172 .readRenderedServicePathFirstHop(rsp.getName());
173 LOG.info("handleRenderedServicePath: firstRspHop: {}", firstRspHop);
175 RenderedServicePathHop firstHop = pathHopList.get(0);
176 RenderedServicePathHop lastHop = pathHopList.get(pathHopList.size()-1);
178 final List<Node> bridgeNodes = nodeCacheManager.getBridgeNodes();
179 if (bridgeNodes == null || bridgeNodes.isEmpty()) {
180 LOG.warn("handleRenderedServicePath: There are no bridges to process");
183 for (RenderedServicePathHop hop : pathHopList) {
184 for (Node bridgeNode : bridgeNodes) {
185 // ignore bridges other than br-int
186 // TODO: Get bridge name from DPL, rework this loop to use DPL list
187 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = southbound.getBridge(bridgeNode, "br-int");
188 if (ovsdbBridgeAugmentation == null) {
191 // TODO: Get port name from the DPL
192 long vxGpeOfPort = getOFPort(bridgeNode, VXGPE);
193 if (vxGpeOfPort == 0L) {
194 LOG.warn("handleRenderedServicePath: Could not identify gpe vtep {} -> OF ({}) on {}",
195 VXGPE, vxGpeOfPort, bridgeNode);
198 long dataPathId = southbound.getDataPathId(bridgeNode);
199 if (dataPathId == 0L) {
200 LOG.warn("handleRenderedServicePath: Could not identify datapathId on {}", bridgeNode);
204 ServiceFunction serviceFunction =
205 SfcProviderServiceFunctionAPI.readServiceFunction(hop.getServiceFunctionName());
206 if (serviceFunction == null) {
207 LOG.warn("handleRenderedServicePath: Could not identify ServiceFunction {} on {}",
208 hop.getServiceFunctionName().getValue(), bridgeNode);
211 ServiceFunctionForwarder serviceFunctionForwarder =
212 SfcProviderServiceForwarderAPI
213 .readServiceFunctionForwarder(hop.getServiceFunctionForwarder());
214 if (serviceFunctionForwarder == null) {
215 LOG.warn("handleRenderedServicePath: Could not identify ServiceFunctionForwarder {} on {}",
216 hop.getServiceFunctionName().getValue(), bridgeNode);
220 handleSf(bridgeNode, serviceFunction, rsp);
221 handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, firstHop, lastHop,
222 entry.getRuleName(), matches, vxGpeOfPort, rsp);
223 if (firstHop == lastHop) {
224 handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, null, lastHop,
225 entry.getRuleName(), matches, vxGpeOfPort, rsp);
231 private void handleSff(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder,
232 ServiceFunction serviceFunction,
233 RenderedServicePathHop hop,
234 RenderedServicePathHop firstHop,
235 RenderedServicePathHop lastHop,
236 String ruleName, Matches matches,
237 long vxGpeOfPort, RenderedServicePath rsp) {
238 long dataPathId = southbound.getDataPathId(bridgeNode);
240 if (hop == firstHop) {
241 LOG.info("handleSff: first hop processing {} - {}",
242 bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
243 NshUtils nshHeader = new NshUtils();
244 nshHeader.setNshNsp(rsp.getPathId());
245 nshHeader.setNshNsi(firstHop.getServiceIndex());
246 Ip sffIp = sfcUtils.getSffIp(lastHop.getServiceFunctionForwarder());
247 nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(sffIp.getIp().getIpv4Address()));
248 if (isSffOnBridge(bridgeNode, serviceFunctionForwarder)) {
249 LOG.info("handleSff: sff and bridge are the same: {} - {}, skipping first sff",
250 bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
251 Ip ip = sfcUtils.getSfIp(serviceFunction);
252 nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
253 nshHeader.setNshTunUdpPort(ip.getPort());
254 sfcClassifierService.programIngressClassifier(dataPathId, ruleName, matches,
255 rsp.getPathId(), rsp.getStartingIndex(),
256 nshHeader, 0, rsp.getName().getValue(), true);
258 LOG.info("handleSff: sff and bridge are not the same: {} - {}, sending to first sff",
259 bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
260 Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
261 nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
262 nshHeader.setNshTunUdpPort(ip.getPort());
263 sfcClassifierService.programIngressClassifier(dataPathId, ruleName, matches,
264 rsp.getPathId(), rsp.getStartingIndex(),
265 nshHeader, vxGpeOfPort, rsp.getName().getValue(), true);
267 } else if (hop == lastHop) {
268 LOG.info("handleSff: last hop processing {} - {}",
269 bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
270 short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
271 String sfDplPortName = sfcUtils.getSfDplPortId(serviceFunction);
272 long sfOfPort = getSfPort(bridgeNode, sfDplPortName);
273 // TODO: Coexistence: SFC flows should take this using new egressTable REST
274 sfcClassifierService.programEgressClassifier(dataPathId, vxGpeOfPort, rsp.getPathId(),
275 lastServiceindex, sfOfPort, 0, rsp.getName().getValue(), true);
276 // TODO: Coexistence: This flow should like like one above, change port, add reg0=1, resubmit
277 sfcClassifierService.programEgressClassifierBypass(dataPathId, vxGpeOfPort, rsp.getPathId(),
278 lastServiceindex, sfOfPort, 0, rsp.getName().getValue(), true);
280 // add typical sff flows
283 // TODO: Coexistence: SFC flows should take this using new tableOffset REST
284 //sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
287 void handleSf(Node bridgeNode, ServiceFunction serviceFunction, RenderedServicePath rsp) {
288 if (isSfOnBridge(bridgeNode, serviceFunction)) {
289 LOG.info("handleSf: sf and bridge are on the same node: {} - {}, adding workaround and arp",
290 bridgeNode.getNodeId().getValue(), serviceFunction.getName().getValue());
291 long dataPathId = southbound.getDataPathId(bridgeNode);
292 Ip ip = sfcUtils.getSfIp(serviceFunction);
293 String sfIpAddr = String.valueOf(ip.getIp().getValue());
294 int sfIpPort = ip.getPort().getValue(); //GPE_PORT
295 String sfDplPortName = sfcUtils.getSfDplPortId(serviceFunction);
296 long sfOfPort = getSfPort(bridgeNode, sfDplPortName);
297 String sfMac = getMacFromExternalIds(bridgeNode, sfDplPortName);
299 LOG.warn("handleSff: could not find mac for {} on {}", sfDplPortName, bridgeNode);
302 //should be sffdplport, but they should all be the same 6633/4790
303 // TODO: Coexistence: SFC flows should take this using new sf dpl augmentation
305 sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, rsp.getName().getValue(), true);
306 sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplPortName,
307 rsp.getName().getValue(), true);
309 sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr,
310 rsp.getName().getValue(), true);
312 LOG.info("handleSf: sf and bridge are not on the same node: {} - {}, do nothing",
313 bridgeNode.getNodeId().getValue(), serviceFunction.getName().getValue());
317 private boolean isSffOnBridge(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder) {
319 Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
320 Node ovsdbNode = southbound.readOvsdbNode(bridgeNode);
321 if (ovsdbNode != null) {
322 localIp = getLocalip(ovsdbNode);
324 LOG.info("isSffOnBridge: {}: {}, localIp: {}, sff ip: {}",
325 bridgeNode.getNodeId().getValue(),
326 localIp.equals(String.valueOf(ip.getIp().getValue())),
327 localIp, ip.getIp().getValue());
328 return localIp.equals(String.valueOf(ip.getIp().getValue()));
331 private String getLocalip(Node ovsdbNode) {
332 Preconditions.checkNotNull(ovsdbNode, "The ovsdbNode was null");
333 String localIp = null;
334 if (ovsdbNode != null) {
335 OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
336 if (ovsdbNodeAugmentation != null && ovsdbNodeAugmentation.getOpenvswitchOtherConfigs() != null) {
337 localIp = southbound.getOtherConfig(ovsdbNode, OvsdbTables.OPENVSWITCH, TUNNEL_ENDPOINT_KEY);
340 if (localIp == null) {
341 LOG.warn("local_ip was not found for node: {}", ovsdbNode);
347 private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
348 String sfDplPortName = sfcUtils.getSfDplPortId(serviceFunction);
349 long sfOfPort = getSfPort(bridgeNode, sfDplPortName);
350 LOG.info("isSfOnBridge: {}: {}, sfOfPort: {}", bridgeNode.getNodeId().getValue(), sfOfPort != 0L, sfOfPort);
351 return sfOfPort != 0L;
354 private Ace getAceFromRenderedServicePath(RenderedServicePath rsp) {
355 Preconditions.checkNotNull(rsp, "RSP cannot be null");
357 //String rspName = rsp.getName().getValue();
358 //String rspNameSuffix = "_rsp";
359 //String sfcName = rspName.substring(0, rspName.length() - rspNameSuffix.length());
360 //String sfcName = rsp.getServiceChainName().getValue()
361 //LOG.info("getAceFromRenderedServicePath: rsp: {}, sfcName: {}", rsp, sfcName);
362 ace = sfcUtils.getAce(rsp);
367 private RenderedServicePath getRenderedServicePath (Ace entry) {
368 RenderedServicePath rsp = null;
369 RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
370 LOG.debug("getRenderedServicePath: Processing ACL entry = {} sfcRedirect = {}",
371 entry.getRuleName(), sfcRedirect);
372 if (sfcRedirect == null) {
373 LOG.warn("getRenderedServicePath: sfcRedirect is null");
377 if (sfcRedirect.getRspName() != null) {
378 rsp = getRenderedServicePathFromRsp(sfcRedirect.getRspName());
379 } else if (sfcRedirect.getSfpName() != null) {
380 LOG.warn("getRenderedServicePath: by sfp not handled yet");
382 rsp = getRenderedServicePathFromSfc(entry);
384 LOG.info("getRenderedServicePath: rsp: {}", rsp);
388 private RenderedServicePath getRenderedServicePathFromRsp(String rspName) {
389 return sfcUtils.getRsp(rspName);
392 private RenderedServicePath getRenderedServicePathFromSfc (Ace entry) {
393 RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
394 LOG.debug("getRenderedServicePathFromSfc: Processing ACL entry = {} sfcRedirect = {}",
395 entry.getRuleName(), sfcRedirect);
396 if (sfcRedirect == null) {
397 LOG.warn("getRenderedServicePathFromSfc: sfcRedirect is null");
401 String sfcName = sfcRedirect.getSfcName();
402 ServiceFunctionPath sfp = sfcUtils.getSfp(sfcName);
403 if (sfp == null || sfp.getName() == null) {
404 LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
408 LOG.debug("getRenderedServicePathFromSfc: Processing Redirect to SFC = {}, SFP = {}", sfcName, sfp);
409 // If RSP doesn't exist, create an RSP.
410 String sfpName = sfp.getName().getValue();
411 RenderedServicePath rsp = sfcUtils.getRspforSfp(sfpName);
412 String rspName = sfp.getName().getValue() + "_rsp";
414 if (!sfcRedirect.isRenderRsp()) {
415 LOG.info("getRenderedServicePathFromSfc: will not create RSP");
418 LOG.info("getRenderedServicePathFromSfc: No configured RSP corresponding to SFP = {}, "
419 + "Creating new RSP = {}", sfpName, rspName);
420 CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
421 .setParentServiceFunctionPath(sfpName)
423 .setSymmetric(sfp.isSymmetric())
425 rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
427 LOG.warn("getRenderedServicePathFromSfc: failed to add RSP");
431 // If SFP is symmetric, create RSP in the reverse direction.
432 if (sfp.isSymmetric()) {
433 LOG.warn("getRenderedServicePathFromSfc: symmetric RSP is not supported yet");
434 /*LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
435 String rspNameRev = rspName + "-Reverse";
436 RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
437 sfcUtils.getRspId(rspNameRev));
438 if (rspReverse == null) {
439 rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
440 if (rspReverse == null) {
441 LOG.warn("failed to add reverse RSP");
450 private long getSfPort(Node bridgeNode, String sfPortName) {
451 return getOFPort(bridgeNode, sfPortName);
454 private long getOFPort(Node bridgeNode, String portName) {
456 OvsdbTerminationPointAugmentation port =
457 southbound.extractTerminationPointAugmentation(bridgeNode, portName);
459 ofPort = southbound.getOFPort(port);
462 for (int i = 0; i < 5; i++) {
463 LOG.info("Looking for ofPort {}, try: {}", portName, i);
464 TerminationPoint tp = southbound.readTerminationPoint(bridgeNode, null, portName);
466 port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
468 ofPort = southbound.getOFPort(port);
469 LOG.info("found ofPort {} - {}, try: {}", portName, ofPort, i);
475 } catch (InterruptedException e) {
476 LOG.error("Interrupted while waiting for ofPort {}", portName, e);
483 private String getMacFromExternalIds(Node bridgeNode, String portName) {
485 OvsdbTerminationPointAugmentation port = southbound.getTerminationPointOfBridge(bridgeNode, portName);
486 LOG.info("getMac: portName: {}, bridgeNode: {},,, port: {}", portName, bridgeNode, port);
487 if (port != null && port.getInterfaceExternalIds() != null) {
488 mac = southbound.getInterfaceExternalIdsValue(port, Constants.EXTERNAL_ID_VM_MAC);
494 public void setDependencies(ServiceReference serviceReference) {
495 nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
496 southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
497 sfcClassifierService =
498 (ISfcClassifierService) ServiceHelper.getGlobalInstance(ISfcClassifierService.class, this);
499 LOG.info("sfcClassifierService= {}", sfcClassifierService);