2 * Copyright (c) 2014, 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.impl;
11 import org.opendaylight.netvirt.openstack.netvirt.ConfigInterface;
12 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
13 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
14 import org.opendaylight.netvirt.openstack.netvirt.api.EgressAclProvider;
15 import org.opendaylight.netvirt.openstack.netvirt.api.IngressAclProvider;
16 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
17 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
18 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
19 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
20 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
21 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityRule;
22 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSubnet;
23 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
24 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
25 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronPortCRUD;
26 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSubnetCRUD;
27 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
31 import org.osgi.framework.ServiceReference;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import java.util.ArrayList;
36 import java.util.List;
38 public class SecurityServicesImpl implements ConfigInterface, SecurityServicesManager {
40 private static final Logger LOG = LoggerFactory.getLogger(TenantNetworkManagerImpl.class);
41 private volatile INeutronPortCRUD neutronPortCache;
42 private volatile INeutronSubnetCRUD neutronSubnetCache;
43 private volatile Southbound southbound;
44 private volatile INeutronNetworkCRUD neutronNetworkCache;
45 private volatile ConfigurationService configurationService;
46 private volatile IngressAclProvider ingressAclProvider;
47 private volatile EgressAclProvider egressAclProvider;
48 private volatile NeutronL3Adapter neutronL3Adapter;
49 private boolean isConntrackEnabled = false;
51 public SecurityServicesImpl() {
55 public SecurityServicesImpl(boolean isConntrack) {
57 this.isConntrackEnabled = isConntrack;
61 public boolean isPortSecurityReady(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
62 if (neutronPortCache == null) {
63 LOG.error("neutron port is null");
66 LOG.trace("isPortSecurityReady for {}", terminationPointAugmentation.getName());
67 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
68 Constants.EXTERNAL_ID_INTERFACE_ID);
69 if (neutronPortId == null) {
72 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
73 if (neutronPort == null) {
74 neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
75 if (neutronPort == null) {
76 LOG.error("isPortSecurityReady for {}", terminationPointAugmentation.getName()
81 String deviceOwner = neutronPort.getDeviceOwner();
82 if (!deviceOwner.contains("compute")) {
83 LOG.debug("Port {} is not a compute host, it is a: {}", neutronPortId, deviceOwner);
85 LOG.debug("isPortSecurityReady() is a {} ", deviceOwner);
86 List<NeutronSecurityGroup> securityGroups = neutronPort.getSecurityGroups();
87 if (securityGroups.isEmpty()) {
88 LOG.debug("Check for device: {} does not contain a Security Group for port: {}", deviceOwner,
92 LOG.debug("Security Group Check {} does contain a Neutron Security Group", neutronPortId);
97 public List<NeutronSecurityGroup> getSecurityGroupInPortList(OvsdbTerminationPointAugmentation
98 terminationPointAugmentation) {
99 List<NeutronSecurityGroup> neutronSecurityGroups = new ArrayList<>();
100 if (neutronPortCache == null) {
101 LOG.error("neutron port is null");
102 return neutronSecurityGroups;
104 LOG.trace("getSecurityGroupInPortList for {}", terminationPointAugmentation.getName());
105 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
106 Constants.EXTERNAL_ID_INTERFACE_ID);
107 if (neutronPortId == null) {
108 return neutronSecurityGroups;
110 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
111 if (neutronPort == null) {
112 neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
113 if (neutronPort == null) {
114 LOG.error("getSecurityGroupInPortList for {}", terminationPointAugmentation.getName()
116 return neutronSecurityGroups;
119 neutronSecurityGroups = neutronPort.getSecurityGroups();
120 return neutronSecurityGroups;
125 public NeutronPort getDhcpServerPort(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
126 if (neutronPortCache == null) {
127 LOG.warn("getDHCPServerPort: neutron port cache is null");
129 LOG.trace("getDHCPServerPort for {}",
130 terminationPointAugmentation.getName());
131 NeutronPort neutronPort = null;
133 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
134 Constants.EXTERNAL_ID_INTERFACE_ID);
135 if (neutronPortId == null) {
138 if (null != neutronPortCache) {
139 neutronPort = neutronPortCache.getPort(neutronPortId);
142 if (neutronPort == null) {
143 neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
144 if (neutronPort == null) {
145 LOG.error("getDHCPServerPort: neutron port of {} is not found", neutronPortId);
148 LOG.info("getDHCPServerPort: neutron port of {} got from cleanupcache", neutronPortId);
151 /* if the current port is a DHCP port, return the same*/
152 if (neutronPort.getDeviceOwner().contains("dhcp")) {
155 /* if the current port is a DHCP port, return the same*/
156 if (neutronPort.getDeviceOwner().contains("dhcp")) {
159 /*Since all the fixed ip assigned to a port should be
160 *from the same network, first port is sufficient.*/
161 List<Neutron_IPs> fixedIps = neutronPort.getFixedIPs();
162 if (null == fixedIps || 0 == fixedIps.size() ) {
163 LOG.error("getDHCPServerPort: No fixed ip is assigned");
166 /* Get all the ports in the subnet and identify the dhcp port*/
167 String subnetUuid = fixedIps.iterator().next().getSubnetUUID();
168 NeutronSubnet neutronSubnet = neutronSubnetCache.getSubnet(subnetUuid);
169 if (neutronSubnet == null) {
170 LOG.error("getDHCPServerPort: No subnet is found for " + subnetUuid);
173 List<NeutronPort> ports = neutronSubnet.getPortsInSubnet();
174 for (NeutronPort port : ports) {
175 if (port.getDeviceOwner().contains("dhcp")) {
179 } catch (Exception e) {
180 LOG.error("getDHCPServerPort:getDHCPServerPort failed due to ", e);
187 public NeutronPort getNeutronPortFromDhcpIntf(
188 OvsdbTerminationPointAugmentation terminationPointAugmentation) {
189 if (neutronPortCache == null) {
190 LOG.error("getNeutronPortFromDhcpIntf: neutron port is null");
193 String neutronPortId = southbound.getInterfaceExternalIdsValue(
194 terminationPointAugmentation,
195 Constants.EXTERNAL_ID_INTERFACE_ID);
196 if (neutronPortId == null) {
199 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
200 if (neutronPort == null) {
201 neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
202 if (neutronPort == null) {
203 LOG.error("getNeutronPortFromDhcpIntf: neutron port of {} is not found", neutronPortId);
207 /* if the current port is a DHCP port, return true*/
208 if (neutronPort.getDeviceOwner().contains("dhcp")) {
209 LOG.trace("getNeutronPortFromDhcpIntf: neutronPort is a dhcp port", neutronPort );
217 public NeutronPort getNeutronPortFromCache(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
218 NeutronPort neutronPort = null;
219 LOG.trace("getNeutronPortFromCache for {}",
220 terminationPointAugmentation.getName());
222 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
223 Constants.EXTERNAL_ID_INTERFACE_ID);
224 if (neutronPortId == null) {
227 if (null != neutronPortCache) {
228 neutronPort = neutronPortCache.getPort(neutronPortId);
231 if (neutronPort == null) {
232 LOG.trace("getNeutronPortFromCache: neutron port of {} search in cleanupcache", neutronPortId);
234 neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
235 if (neutronPort == null) {
236 LOG.error("getNeutronPortFromCache: neutron port of {} is not found", neutronPortId);
239 LOG.trace("getNeutronPortFromCache: neutron port of {} got from cleanupcache", neutronPortId);
242 } catch (Exception e) {
243 LOG.warn("getNeutronPortFromCache:getNeutronPortFromCache failed due to ", e);
252 public boolean isComputePort(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
253 if (neutronPortCache == null) {
254 LOG.warn("isComputePort : neutronPortCache is null");
256 NeutronPort neutronPort = null;
257 LOG.trace("isComputePort for {}", terminationPointAugmentation.getName());
258 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
259 Constants.EXTERNAL_ID_INTERFACE_ID);
260 if (neutronPortId == null) {
263 if (neutronPortCache != null) {
264 neutronPort = neutronPortCache.getPort(neutronPortId);
266 if (neutronPort == null) {
267 neutronPort = getNeutronPortFromCache(terminationPointAugmentation);
268 if (neutronPort == null) {
272 /*Check the device owner and if it contains compute to identify
273 * whether it is a compute port.*/
274 String deviceOwner = neutronPort.getDeviceOwner();
275 if (!deviceOwner.contains("compute")) {
276 LOG.debug("isComputePort : Port {} is not a DHCP server port for device owner {}",
277 neutronPortId,deviceOwner);
284 public boolean isLastPortinSubnet(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
285 if (neutronPortCache == null) {
286 LOG.error("isLastPortinSubnet: neutronPortCache is null");
288 NeutronPort neutronPort = null;
290 LOG.trace("isLastPortinSubnet: for {}", terminationPointAugmentation.getName());
291 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
292 Constants.EXTERNAL_ID_INTERFACE_ID);
293 if (neutronPortId == null) {
296 if (neutronPortCache != null) {
297 neutronPort = neutronPortCache.getPort(neutronPortId);
299 if (neutronPort == null) {
300 neutronPort = getNeutronPortFromCache(terminationPointAugmentation);
301 if (neutronPort == null) {
302 LOG.error("isLastPortinSubnet: neutron port of {} is not found", neutronPortId);
306 List<Neutron_IPs> neutronPortFixedIp = neutronPort.getFixedIPs();
307 if (null == neutronPortFixedIp || neutronPortFixedIp.isEmpty()) {
310 /*Get all the ports in the current node and check whether there
311 * is any port belonging to the same subnet of the input
313 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
314 if (terminationPoints != null && !terminationPoints.isEmpty()) {
315 for (TerminationPoint tp : terminationPoints) {
316 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
317 tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
318 if (ovsdbTerminationPointAugmentation != null && !ovsdbTerminationPointAugmentation
319 .getName().equals(Constants.INTEGRATION_BRIDGE)) {
320 String portId = southbound.getInterfaceExternalIdsValue(ovsdbTerminationPointAugmentation,
321 Constants.EXTERNAL_ID_INTERFACE_ID);
322 if (null != portId) {
323 NeutronPort port = neutronPortCache.getPort(portId);
324 if (null != port && !(port.getID().equals(neutronPort.getID()))
325 && port.getDeviceOwner().contains("compute")) {
326 List<Neutron_IPs> portFixedIp = port.getFixedIPs();
327 if (null == portFixedIp || portFixedIp.isEmpty()) {
330 if (portFixedIp.iterator().next().getSubnetUUID()
331 .equals(neutronPort.getFixedIPs().iterator().next().getSubnetUUID())) {
332 LOG.trace("isLastPortinSubnet: Port is not the only port.");
340 } catch (Exception e) {
341 LOG.error("isLastPortinSubnet: isLastPortinSubnet failed due to ", e);
348 public boolean isLastPortinBridge(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
349 LOG.trace("isLastPortinBridge: for {}", terminationPointAugmentation.getName());
350 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
351 /*Check whether the node has any port other than br-int*/
352 if (terminationPoints != null && !terminationPoints.isEmpty()) {
353 for (TerminationPoint tp : terminationPoints) {
354 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
355 tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
356 if (null != ovsdbTerminationPointAugmentation
357 && !(ovsdbTerminationPointAugmentation.getName().equals(Constants.INTEGRATION_BRIDGE))
358 && !(terminationPointAugmentation.getInterfaceUuid()
359 .equals(ovsdbTerminationPointAugmentation.getInterfaceUuid()))) {
360 LOG.debug("isLastPortinBridge: it the last port in bridge {}",
361 terminationPointAugmentation.getName());
370 public List<Neutron_IPs> getIpAddressList(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
371 if (neutronPortCache == null) {
372 LOG.warn("getIpAddress: neutronPortCache is null");
374 NeutronPort neutronPort = null;
375 LOG.trace("getIpAddress: for {}", terminationPointAugmentation.getName());
376 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
377 Constants.EXTERNAL_ID_INTERFACE_ID);
378 if (neutronPortId == null) {
381 if (neutronPortCache != null) {
382 neutronPort = neutronPortCache.getPort(neutronPortId);
384 if (neutronPort == null) {
385 neutronPort = getNeutronPortFromCache(terminationPointAugmentation);
387 if (neutronPort == null) {
388 LOG.error("getIpAddress: neutron port of {} is not found", neutronPortId);
391 return neutronPort.getFixedIPs();
395 public List<Neutron_IPs> getVmListForSecurityGroup(String portUuid, String securityGroupUuid) {
396 List<Neutron_IPs> vmListForSecurityGroup = new ArrayList<>();
397 /*For every port check whether security grouplist contains the current
400 for (String neutronPortUuid:neutronL3Adapter.getPortCleanupCache().keySet()) {
401 NeutronPort neutronPort = neutronL3Adapter.getPortCleanupCache().get(neutronPortUuid);
402 if (!neutronPort.getDeviceOwner().contains("compute")) {
403 LOG.debug("getVMListForSecurityGroup : the port {} is not "
404 + "compute port belongs to {}", neutronPort.getID(), neutronPort.getDeviceOwner());
407 if (portUuid.equals(neutronPort.getID())) {
410 List<NeutronSecurityGroup> securityGroups = neutronPort.getSecurityGroups();
411 if (null != securityGroups) {
412 for (NeutronSecurityGroup securityGroup:securityGroups) {
413 if (securityGroup.getSecurityGroupUUID().equals(securityGroupUuid)) {
414 LOG.debug("getVMListForSecurityGroup : adding ports with ips {} "
415 + "compute port", neutronPort.getFixedIPs());
416 if (neutronPort.getFixedIPs() != null) {
417 vmListForSecurityGroup.addAll(neutronPort.getFixedIPs());
424 } catch (Exception e) {
425 LOG.error("getVMListForSecurityGroup: getVMListForSecurityGroup"
426 + " failed due to ", e);
429 return vmListForSecurityGroup;
434 public void syncSecurityGroup(NeutronPort port, List<NeutronSecurityGroup> securityGroupList, boolean write) {
435 LOG.trace("syncSecurityGroup:" + securityGroupList + " Write:" + write);
436 if (null != port && null != port.getSecurityGroups()) {
437 Node node = getNode(port);
441 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
442 if (null == neutronNetwork) {
443 neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(port.getNetworkUUID());
445 if (neutronNetwork == null) {
448 String segmentationId = neutronNetwork.getProviderSegmentationID();
449 OvsdbTerminationPointAugmentation intf = getInterface(node, port);
453 long localPort = southbound.getOFPort(intf);
454 String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
455 if (attachedMac == null) {
456 LOG.debug("programVlanRules: No AttachedMac seen in {}", intf);
459 long dpid = getDpidOfIntegrationBridge(node);
463 String neutronPortId = southbound.getInterfaceExternalIdsValue(intf,
464 Constants.EXTERNAL_ID_INTERFACE_ID);
465 if (neutronPortId == null) {
466 LOG.debug("syncSecurityGroup: No neutronPortId seen in {}", intf);
469 for (NeutronSecurityGroup securityGroupInPort:securityGroupList) {
470 ingressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
471 securityGroupInPort, neutronPortId, write);
472 egressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
473 securityGroupInPort, neutronPortId, write);
479 public void syncSecurityRule(NeutronPort port, NeutronSecurityRule securityRule,Neutron_IPs vmIp, boolean write) {
480 LOG.trace("syncSecurityGroup:" + securityRule + " Write:" + write);
481 if (null != port && null != port.getSecurityGroups()) {
482 Node node = getNode(port);
486 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
487 if (null == neutronNetwork) {
488 neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(port.getNetworkUUID());
490 if (neutronNetwork == null) {
493 String segmentationId = neutronNetwork.getProviderSegmentationID();
494 OvsdbTerminationPointAugmentation intf = getInterface(node, port);
498 long localPort = southbound.getOFPort(intf);
499 String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
500 if (attachedMac == null) {
501 LOG.debug("programVlanRules: No AttachedMac seen in {}", intf);
504 long dpid = getDpidOfIntegrationBridge(node);
508 if (NeutronSecurityRule.ETHERTYPE_IPV4.equals(securityRule.getSecurityRuleEthertype())) {
509 if (NeutronSecurityRule.DIRECTION_INGRESS.equals(securityRule.getSecurityRuleDirection())) {
510 ingressAclProvider.programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
511 securityRule, vmIp, write);
512 } else if (NeutronSecurityRule.DIRECTION_EGRESS.equals(securityRule.getSecurityRuleDirection())) {
513 egressAclProvider.programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
514 securityRule, vmIp, write);
520 private long getDpidOfIntegrationBridge(Node node) {
521 LOG.trace("getDpidOfIntegrationBridge:" + node);
523 if (southbound.getBridgeName(node).equals(configurationService.getIntegrationBridgeName())) {
524 dpid = getDpid(node);
527 LOG.warn("getDpidOfIntegerationBridge: dpid not found: {}", node);
532 private long getDpid(Node node) {
533 LOG.trace("getDpid" + node);
534 long dpid = southbound.getDataPathId(node);
536 LOG.warn("getDpid: dpid not found: {}", node);
541 private Node getNode(NeutronPort port) {
542 LOG.trace("getNode:Port" + port);
543 List<Node> toplogyNodes = southbound.readOvsdbTopologyNodes();
545 for (Node topologyNode : toplogyNodes) {
547 Node node = southbound.getBridgeNode(topologyNode,Constants.INTEGRATION_BRIDGE);
548 List<OvsdbTerminationPointAugmentation> ovsdbPorts = southbound.getTerminationPointsOfBridge(node);
549 for (OvsdbTerminationPointAugmentation ovsdbPort : ovsdbPorts) {
550 String uuid = southbound.getInterfaceExternalIdsValue(ovsdbPort,
551 Constants.EXTERNAL_ID_INTERFACE_ID);
552 if (null != uuid && uuid.equals(port.getID())) {
556 } catch (Exception e) {
557 LOG.error("Exception during handlingNeutron network delete", e);
560 LOG.info("no node found for port:" + port);
564 private OvsdbTerminationPointAugmentation getInterface(Node node, NeutronPort port) {
565 LOG.trace("getInterface:Node:" + node + " Port:" + port);
567 List<OvsdbTerminationPointAugmentation> ovsdbPorts = southbound.getTerminationPointsOfBridge(node);
568 for (OvsdbTerminationPointAugmentation ovsdbPort : ovsdbPorts) {
569 String uuid = southbound.getInterfaceExternalIdsValue(ovsdbPort,
570 Constants.EXTERNAL_ID_INTERFACE_ID);
571 if (null != uuid && uuid.equals(port.getID())) {
575 } catch (Exception e) {
576 LOG.error("Exception during handlingNeutron network delete", e);
578 LOG.info("no interface found for node: " + node + " port:" + port);
583 public void setDependencies(ServiceReference serviceReference) {
585 (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
587 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
588 neutronNetworkCache =
589 (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
590 configurationService =
591 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
595 public void setDependencies(Object impl) {
596 if (impl instanceof INeutronPortCRUD) {
597 neutronPortCache = (INeutronPortCRUD)impl;
598 } else if (impl instanceof INeutronSubnetCRUD) {
599 neutronSubnetCache = (INeutronSubnetCRUD) impl;
600 } else if (impl instanceof IngressAclProvider) {
601 ingressAclProvider = (IngressAclProvider) impl;
602 } else if (impl instanceof EgressAclProvider) {
603 egressAclProvider = (EgressAclProvider) impl;
608 public boolean isConntrackEnabled() {
609 return isConntrackEnabled;