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.ovsdb.openstack.netvirt.impl;
11 import org.opendaylight.ovsdb.openstack.netvirt.ConfigInterface;
12 import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
13 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
14 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
15 import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
18 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronNetwork;
19 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort;
20 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
21 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
22 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSubnet;
23 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
24 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
25 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronPortCRUD;
26 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronSubnetCRUD;
27 import org.opendaylight.ovsdb.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) {
76 String deviceOwner = neutronPort.getDeviceOwner();
77 if (!deviceOwner.contains("compute")) {
78 LOG.debug("Port {} is not a compute host, it is a: {}", neutronPortId, deviceOwner);
80 LOG.debug("isPortSecurityReady() is a {} ", deviceOwner);
81 List<NeutronSecurityGroup> securityGroups = neutronPort.getSecurityGroups();
82 if (securityGroups.isEmpty()) {
83 LOG.debug("Check for device: {} does not contain a Security Group for port: {}", deviceOwner,
87 LOG.debug("Security Group Check {} does contain a Neutron Security Group", neutronPortId);
92 public List<NeutronSecurityGroup> getSecurityGroupInPortList(OvsdbTerminationPointAugmentation
93 terminationPointAugmentation) {
94 List<NeutronSecurityGroup> neutronSecurityGroups = new ArrayList<>();
95 if (neutronPortCache == null) {
96 LOG.error("neutron port is null");
97 return neutronSecurityGroups;
99 LOG.trace("isPortSecurityReady for {}", terminationPointAugmentation.getName());
100 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
101 Constants.EXTERNAL_ID_INTERFACE_ID);
102 if (neutronPortId == null) {
103 return neutronSecurityGroups;
105 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
106 if (neutronPort == null) {
107 return neutronSecurityGroups;
109 neutronSecurityGroups = neutronPort.getSecurityGroups();
110 return neutronSecurityGroups;
115 public NeutronPort getDhcpServerPort(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
116 if (neutronPortCache == null) {
117 LOG.warn("getDHCPServerPort: neutron port cache is null");
119 LOG.trace("getDHCPServerPort for {}",
120 terminationPointAugmentation.getName());
121 NeutronPort neutronPort = null;
123 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
124 Constants.EXTERNAL_ID_INTERFACE_ID);
125 if (neutronPortId == null) {
128 if (null != neutronPortCache) {
129 neutronPort = neutronPortCache.getPort(neutronPortId);
132 if (neutronPort == null ){
133 neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
134 if (neutronPort == null)
136 LOG.info("getDHCPServerPort: neutron port of {} is not found", neutronPortId);
139 LOG.info("getDHCPServerPort: neutron port of {} got from cleanupcache", neutronPortId);
142 /* if the current port is a DHCP port, return the same*/
143 if (neutronPort.getDeviceOwner().contains("dhcp")) {
146 /* if the current port is a DHCP port, return the same*/
147 if (neutronPort.getDeviceOwner().contains("dhcp")) {
150 /*Since all the fixed ip assigned to a port should be
151 *from the same network, first port is sufficient.*/
152 List<Neutron_IPs> fixedIps = neutronPort.getFixedIPs();
153 if (null == fixedIps || 0 == fixedIps.size() ) {
154 LOG.error("getDHCPServerPort: No fixed ip is assigned");
157 /* Get all the ports in the subnet and identify the dhcp port*/
158 String subnetUuid = fixedIps.iterator().next().getSubnetUUID();
159 NeutronSubnet neutronSubnet = neutronSubnetCache.getSubnet(subnetUuid);
160 if (neutronSubnet == null) {
161 LOG.error("getDHCPServerPort: No subnet is found for " + subnetUuid);
164 List<NeutronPort> ports = neutronSubnet.getPortsInSubnet();
165 for (NeutronPort port : ports) {
166 if (port.getDeviceOwner().contains("dhcp")) {
170 } catch (Exception e) {
171 LOG.error("getDHCPServerPort:getDHCPServerPort failed due to ", e);
178 public NeutronPort getNeutronPortFromDhcpIntf(
179 OvsdbTerminationPointAugmentation terminationPointAugmentation) {
180 if (neutronPortCache == null) {
181 LOG.error("getNeutronPortFromDhcpIntf: neutron port is null");
184 String neutronPortId = southbound.getInterfaceExternalIdsValue(
185 terminationPointAugmentation,
186 Constants.EXTERNAL_ID_INTERFACE_ID);
187 if (neutronPortId == null) {
190 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
191 if (neutronPort == null) {
192 LOG.error("getNeutronPortFromDhcpIntf: neutron port of {} is not found", neutronPortId);
195 /* if the current port is a DHCP port, return true*/
196 if (neutronPort.getDeviceOwner().contains("dhcp")) {
197 LOG.trace("getNeutronPortFromDhcpIntf: neutronPort is a dhcp port", neutronPort );
205 public NeutronPort getNeutronPortFromCache(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
206 NeutronPort neutronPort = null;
207 LOG.trace("getNeutronPortFromCache for {}",
208 terminationPointAugmentation.getName());
210 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
211 Constants.EXTERNAL_ID_INTERFACE_ID);
212 if (neutronPortId == null) {
215 if (null != neutronPortCache) {
216 neutronPort = neutronPortCache.getPort(neutronPortId);
219 if (neutronPort == null ){
220 LOG.trace("getNeutronPortFromCache: neutron port of {} search in cleanupcache", neutronPortId);
222 neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
223 if (neutronPort == null)
225 LOG.info("getNeutronPortFromCache: neutron port of {} is not found", neutronPortId);
228 LOG.trace("getNeutronPortFromCache: neutron port of {} got from cleanupcache", neutronPortId);
231 }catch (Exception e) {
232 LOG.warn("getNeutronPortFromCache:getNeutronPortFromCache failed due to ", e);
241 public boolean isComputePort(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
242 if (neutronPortCache == null) {
243 LOG.warn("isComputePort : neutronPortCache is null");
245 NeutronPort neutronPort = null;
246 LOG.trace("isComputePort for {}", terminationPointAugmentation.getName());
247 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
248 Constants.EXTERNAL_ID_INTERFACE_ID);
249 if (neutronPortId == null) {
252 if (neutronPortCache != null) {
253 neutronPort = neutronPortCache.getPort(neutronPortId);
255 if (neutronPort == null) {
256 neutronPort = getNeutronPortFromCache(terminationPointAugmentation);
257 if (neutronPort == null)
260 /*Check the device owner and if it contains compute to identify
261 * whether it is a compute port.*/
262 String deviceOwner = neutronPort.getDeviceOwner();
263 if (!deviceOwner.contains("compute")) {
264 LOG.debug("isComputePort : Port {} is not a DHCP server port for device owner {}",
265 neutronPortId,deviceOwner);
272 public boolean isLastPortinSubnet(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
273 if (neutronPortCache == null) {
274 LOG.error("isLastPortinSubnet: neutronPortCache is null");
276 NeutronPort neutronPort = null;
278 LOG.trace("isLastPortinSubnet: for {}", terminationPointAugmentation.getName());
279 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
280 Constants.EXTERNAL_ID_INTERFACE_ID);
281 if (neutronPortId == null) {
284 if (neutronPortCache != null) {
285 neutronPort = neutronPortCache.getPort(neutronPortId);
287 if (neutronPort == null) {
288 neutronPort = getNeutronPortFromCache(terminationPointAugmentation);
289 if (neutronPort == null) {
290 LOG.error("isLastPortinSubnet: neutron port of {} is not found", neutronPortId);
294 List<Neutron_IPs> neutronPortFixedIp = neutronPort.getFixedIPs();
295 if (null == neutronPortFixedIp || neutronPortFixedIp.isEmpty()) {
298 /*Get all the ports in the current node and check whether there
299 * is any port belonging to the same subnet of the input
301 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
302 if (terminationPoints != null && !terminationPoints.isEmpty()) {
303 for (TerminationPoint tp : terminationPoints) {
304 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
305 tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
306 if (ovsdbTerminationPointAugmentation != null && !ovsdbTerminationPointAugmentation
307 .getName().equals(Constants.INTEGRATION_BRIDGE)) {
308 String portId = southbound.getInterfaceExternalIdsValue(ovsdbTerminationPointAugmentation,
309 Constants.EXTERNAL_ID_INTERFACE_ID);
310 if (null != portId) {
311 NeutronPort port = neutronPortCache.getPort(portId);
312 if (null != port && !(port.getID().equals(neutronPort.getID()))
313 && port.getDeviceOwner().contains("compute")) {
314 List<Neutron_IPs> portFixedIp = port.getFixedIPs();
315 if (null == portFixedIp || portFixedIp.isEmpty()) {
318 if (portFixedIp.iterator().next().getSubnetUUID()
319 .equals(neutronPort.getFixedIPs().iterator().next().getSubnetUUID())) {
320 LOG.trace("isLastPortinSubnet: Port is not the only port.");
328 } catch (Exception e) {
329 LOG.error("isLastPortinSubnet: isLastPortinSubnet failed due to ", e);
336 public boolean isLastPortinBridge(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
337 LOG.trace("isLastPortinBridge: for {}", terminationPointAugmentation.getName());
338 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
339 /*Check whether the node has any port other than br-int*/
340 if (terminationPoints != null && !terminationPoints.isEmpty()) {
341 for (TerminationPoint tp : terminationPoints) {
342 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
343 tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
344 if (null != ovsdbTerminationPointAugmentation
345 && !(ovsdbTerminationPointAugmentation.getName().equals(Constants.INTEGRATION_BRIDGE))
346 && !(terminationPointAugmentation.getInterfaceUuid()
347 .equals(ovsdbTerminationPointAugmentation.getInterfaceUuid()))) {
348 LOG.debug("isLastPortinBridge: it the last port in bridge {}",
349 terminationPointAugmentation.getName());
358 public List<Neutron_IPs> getIpAddressList(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
359 if (neutronPortCache == null) {
360 LOG.warn("getIpAddress: neutronPortCache is null");
362 NeutronPort neutronPort = null;
363 LOG.trace("getIpAddress: for {}", terminationPointAugmentation.getName());
364 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
365 Constants.EXTERNAL_ID_INTERFACE_ID);
366 if (neutronPortId == null) {
369 if (neutronPortCache != null) {
370 neutronPort = neutronPortCache.getPort(neutronPortId);
372 if (neutronPort == null) {
373 neutronPort = getNeutronPortFromCache(terminationPointAugmentation);
375 if (neutronPort == null) {
376 LOG.error("getIpAddress: neutron port of {} is not found", neutronPortId);
379 return neutronPort.getFixedIPs();
383 public List<Neutron_IPs> getVmListForSecurityGroup(String portUuid, String securityGroupUuid) {
384 List<Neutron_IPs> vmListForSecurityGroup = new ArrayList<>();
385 /*For every port check whether security grouplist contains the current
388 for (NeutronPort neutronPort:neutronPortCache.getAllPorts()) {
389 if (!neutronPort.getDeviceOwner().contains("compute")) {
390 LOG.debug("getVMListForSecurityGroup : the port {} is not "
391 + "compute port belongs to {}", neutronPort.getID(), neutronPort.getDeviceOwner());
394 if (portUuid.equals(neutronPort.getID())) {
397 List<NeutronSecurityGroup> securityGroups = neutronPort.getSecurityGroups();
398 if (null != securityGroups) {
399 for (NeutronSecurityGroup securityGroup:securityGroups) {
400 if (securityGroup.getSecurityGroupUUID().equals(securityGroupUuid)) {
401 LOG.debug("getVMListForSecurityGroup : adding ports with ips {} "
402 + "compute port", neutronPort.getFixedIPs());
403 if (neutronPort.getFixedIPs() != null) {
404 vmListForSecurityGroup.addAll(neutronPort.getFixedIPs());
411 } catch (Exception e) {
412 LOG.error("getVMListForSecurityGroup: getVMListForSecurityGroup"
413 + " failed due to ", e);
416 return vmListForSecurityGroup;
421 public void syncSecurityGroup(NeutronPort port, List<NeutronSecurityGroup> securityGroupList, boolean write) {
422 LOG.trace("syncSecurityGroup:" + securityGroupList + " Write:" + write);
423 if (null != port && null != port.getSecurityGroups()) {
424 Node node = getNode(port);
428 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
429 if (neutronNetwork == null) {
432 String segmentationId = neutronNetwork.getProviderSegmentationID();
433 OvsdbTerminationPointAugmentation intf = getInterface(node, port);
437 long localPort = southbound.getOFPort(intf);
438 String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
439 if (attachedMac == null) {
440 LOG.debug("programVlanRules: No AttachedMac seen in {}", intf);
443 long dpid = getDpidOfIntegrationBridge(node);
447 String neutronPortId = southbound.getInterfaceExternalIdsValue(intf,
448 Constants.EXTERNAL_ID_INTERFACE_ID);
449 if (neutronPortId == null) {
450 LOG.debug("syncSecurityGroup: No neutronPortId seen in {}", intf);
453 for (NeutronSecurityGroup securityGroupInPort:securityGroupList) {
454 ingressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
455 securityGroupInPort, neutronPortId, write);
456 egressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
457 securityGroupInPort, neutronPortId, write);
463 public void syncSecurityRule(NeutronPort port, NeutronSecurityRule securityRule,Neutron_IPs vmIp, boolean write) {
464 LOG.trace("syncSecurityGroup:" + securityRule + " Write:" + write);
465 if (null != port && null != port.getSecurityGroups()) {
466 Node node = getNode(port);
470 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
471 if (neutronNetwork == null) {
474 String segmentationId = neutronNetwork.getProviderSegmentationID();
475 OvsdbTerminationPointAugmentation intf = getInterface(node, port);
479 long localPort = southbound.getOFPort(intf);
480 String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
481 if (attachedMac == null) {
482 LOG.debug("programVlanRules: No AttachedMac seen in {}", intf);
485 long dpid = getDpidOfIntegrationBridge(node);
489 if ("IPv4".equals(securityRule.getSecurityRuleEthertype())
490 && "ingress".equals(securityRule.getSecurityRuleDirection())) {
492 ingressAclProvider.programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
493 securityRule, vmIp, write);
494 } else if (securityRule.getSecurityRuleEthertype().equals("IPv4")
495 && securityRule.getSecurityRuleDirection().equals("egress")) {
496 egressAclProvider.programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
497 securityRule, vmIp, write);
502 private long getDpidOfIntegrationBridge(Node node) {
503 LOG.trace("getDpidOfIntegrationBridge:" + node);
505 if (southbound.getBridgeName(node).equals(configurationService.getIntegrationBridgeName())) {
506 dpid = getDpid(node);
509 LOG.warn("getDpidOfIntegerationBridge: dpid not found: {}", node);
514 private long getDpid(Node node) {
515 LOG.trace("getDpid" + node);
516 long dpid = southbound.getDataPathId(node);
518 LOG.warn("getDpid: dpid not found: {}", node);
523 private Node getNode(NeutronPort port) {
524 LOG.trace("getNode:Port" + port);
525 List<Node> toplogyNodes = southbound.readOvsdbTopologyNodes();
527 for (Node topologyNode : toplogyNodes) {
529 Node node = southbound.getBridgeNode(topologyNode,Constants.INTEGRATION_BRIDGE);
530 List<OvsdbTerminationPointAugmentation> ovsdbPorts = southbound.getTerminationPointsOfBridge(node);
531 for (OvsdbTerminationPointAugmentation ovsdbPort : ovsdbPorts) {
532 String uuid = southbound.getInterfaceExternalIdsValue(ovsdbPort,
533 Constants.EXTERNAL_ID_INTERFACE_ID);
534 if (null != uuid && uuid.equals(port.getID())) {
538 } catch (Exception e) {
539 LOG.error("Exception during handlingNeutron network delete", e);
542 LOG.info("no node found for port:" + port);
546 private OvsdbTerminationPointAugmentation getInterface(Node node, NeutronPort port) {
547 LOG.trace("getInterface:Node:" + node + " Port:" + port);
549 List<OvsdbTerminationPointAugmentation> ovsdbPorts = southbound.getTerminationPointsOfBridge(node);
550 for (OvsdbTerminationPointAugmentation ovsdbPort : ovsdbPorts) {
551 String uuid = southbound.getInterfaceExternalIdsValue(ovsdbPort,
552 Constants.EXTERNAL_ID_INTERFACE_ID);
553 if (null != uuid && uuid.equals(port.getID())) {
557 } catch (Exception e) {
558 LOG.error("Exception during handlingNeutron network delete", e);
560 LOG.info("no interface found for node: " + node + " port:" + port);
565 public void setDependencies(ServiceReference serviceReference) {
567 (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
569 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
570 neutronNetworkCache =
571 (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
572 configurationService =
573 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
577 public void setDependencies(Object impl) {
578 if (impl instanceof INeutronPortCRUD) {
579 neutronPortCache = (INeutronPortCRUD)impl;
580 } else if (impl instanceof INeutronSubnetCRUD) {
581 neutronSubnetCache = (INeutronSubnetCRUD) impl;
582 } else if (impl instanceof IngressAclProvider) {
583 ingressAclProvider = (IngressAclProvider) impl;
584 } else if (impl instanceof EgressAclProvider) {
585 egressAclProvider = (EgressAclProvider) impl;
590 public boolean isConntrackEnabled() {
591 return isConntrackEnabled;