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 boolean isConntrackEnabled = false;
50 public SecurityServicesImpl() {
54 public SecurityServicesImpl(boolean isConntrack) {
56 this.isConntrackEnabled = isConntrack;
60 public boolean isPortSecurityReady(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
61 if (neutronPortCache == null) {
62 LOG.error("neutron port is null");
65 LOG.trace("isPortSecurityReady for {}", terminationPointAugmentation.getName());
66 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
67 Constants.EXTERNAL_ID_INTERFACE_ID);
68 if (neutronPortId == null) {
71 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
72 if (neutronPort == null) {
75 String deviceOwner = neutronPort.getDeviceOwner();
76 if (!deviceOwner.contains("compute")) {
77 LOG.debug("Port {} is not a compute host, it is a: {}", neutronPortId, deviceOwner);
79 LOG.debug("isPortSecurityReady() is a {} ", deviceOwner);
80 List<NeutronSecurityGroup> securityGroups = neutronPort.getSecurityGroups();
81 if (securityGroups.isEmpty()) {
82 LOG.debug("Check for device: {} does not contain a Security Group for port: {}", deviceOwner,
86 LOG.debug("Security Group Check {} does contain a Neutron Security Group", neutronPortId);
91 public List<NeutronSecurityGroup> getSecurityGroupInPortList(OvsdbTerminationPointAugmentation
92 terminationPointAugmentation) {
93 List<NeutronSecurityGroup> neutronSecurityGroups = new ArrayList<>();
94 if (neutronPortCache == null) {
95 LOG.error("neutron port is null");
96 return neutronSecurityGroups;
98 LOG.trace("isPortSecurityReady for {}", terminationPointAugmentation.getName());
99 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
100 Constants.EXTERNAL_ID_INTERFACE_ID);
101 if (neutronPortId == null) {
102 return neutronSecurityGroups;
104 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
105 if (neutronPort == null) {
106 return neutronSecurityGroups;
108 neutronSecurityGroups = neutronPort.getSecurityGroups();
109 return neutronSecurityGroups;
114 public NeutronPort getDhcpServerPort(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
115 if (neutronPortCache == null) {
116 LOG.error("getDHCPServerPort: neutron port is null");
119 LOG.trace("getDHCPServerPort for {}",
120 terminationPointAugmentation.getName());
122 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
123 Constants.EXTERNAL_ID_INTERFACE_ID);
124 if (neutronPortId == null) {
127 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
128 if (neutronPort == null) {
129 LOG.error("getDHCPServerPort: neutron port of {} is not found", neutronPortId);
132 /* if the current port is a DHCP port, return the same*/
133 if (neutronPort.getDeviceOwner().contains("dhcp")) {
136 /*Since all the fixed ip assigned to a port should be
137 *from the same network, first port is sufficient.*/
138 List<Neutron_IPs> fixedIps = neutronPort.getFixedIPs();
139 if (null == fixedIps || 0 == fixedIps.size() ) {
140 LOG.error("getDHCPServerPort: No fixed ip is assigned");
143 /* Get all the ports in the subnet and identify the dhcp port*/
144 String subnetUuid = fixedIps.iterator().next().getSubnetUUID();
145 NeutronSubnet neutronSubnet = neutronSubnetCache.getSubnet(subnetUuid);
146 if (neutronSubnet == null) {
147 LOG.error("getDHCPServerPort: No subnet is found for " + subnetUuid);
150 List<NeutronPort> ports = neutronSubnet.getPortsInSubnet();
151 for (NeutronPort port : ports) {
152 if (port.getDeviceOwner().contains("dhcp")) {
156 } catch (Exception e) {
157 LOG.error("getDHCPServerPort:getDHCPServerPort failed due to ", e);
164 public NeutronPort getNeutronPortFromDhcpIntf(
165 OvsdbTerminationPointAugmentation terminationPointAugmentation) {
166 if (neutronPortCache == null) {
167 LOG.error("getNeutronPortFromDhcpIntf: neutron port is null");
170 String neutronPortId = southbound.getInterfaceExternalIdsValue(
171 terminationPointAugmentation,
172 Constants.EXTERNAL_ID_INTERFACE_ID);
173 if (neutronPortId == null) {
176 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
177 if (neutronPort == null) {
178 LOG.error("getNeutronPortFromDhcpIntf: neutron port of {} is not found", neutronPortId);
181 /* if the current port is a DHCP port, return true*/
182 if (neutronPort.getDeviceOwner().contains("dhcp")) {
183 LOG.trace("getNeutronPortFromDhcpIntf: neutronPort is a dhcp port", neutronPort );
190 public boolean isComputePort(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
191 if (neutronPortCache == null) {
192 LOG.error("neutron port is null");
195 LOG.trace("isComputePort for {}", terminationPointAugmentation.getName());
196 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
197 Constants.EXTERNAL_ID_INTERFACE_ID);
198 if (neutronPortId == null) {
201 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
202 if (neutronPort == null) {
205 /*Check the device owner and if it contains compute to identify
206 * whether it is a compute port.*/
207 String deviceOwner = neutronPort.getDeviceOwner();
208 if (!deviceOwner.contains("compute")) {
209 LOG.debug("isComputePort : Port {} is not a DHCP server port for device owner {}",
210 neutronPortId,deviceOwner);
217 public boolean isLastPortinSubnet(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
218 if (neutronPortCache == null) {
219 LOG.error("isLastPortinSubnet: neutron port is null");
223 LOG.trace("isLastPortinSubnet: for {}", terminationPointAugmentation.getName());
224 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
225 Constants.EXTERNAL_ID_INTERFACE_ID);
226 if (neutronPortId == null) {
229 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
230 if (neutronPort == null) {
231 LOG.error("isLastPortinSubnet: neutron port of {} is not found", neutronPortId);
234 List<Neutron_IPs> neutronPortFixedIp = neutronPort.getFixedIPs();
235 if (null == neutronPortFixedIp || neutronPortFixedIp.isEmpty()) {
238 /*Get all the ports in the current node and check whether there
239 * is any port belonging to the same subnet of the input
241 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
242 if (terminationPoints != null && !terminationPoints.isEmpty()) {
243 for (TerminationPoint tp : terminationPoints) {
244 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
245 tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
246 if (ovsdbTerminationPointAugmentation != null && !ovsdbTerminationPointAugmentation
247 .getName().equals(Constants.INTEGRATION_BRIDGE)) {
248 String portId = southbound.getInterfaceExternalIdsValue(ovsdbTerminationPointAugmentation,
249 Constants.EXTERNAL_ID_INTERFACE_ID);
250 if (null != portId) {
251 NeutronPort port = neutronPortCache.getPort(portId);
252 if (null != port && !(port.getID().equals(neutronPort.getID()))
253 && port.getDeviceOwner().contains("compute")) {
254 List<Neutron_IPs> portFixedIp = port.getFixedIPs();
255 if (null == portFixedIp || portFixedIp.isEmpty()) {
258 if (portFixedIp.iterator().next().getSubnetUUID()
259 .equals(neutronPort.getFixedIPs().iterator().next().getSubnetUUID())) {
260 LOG.trace("isLastPortinSubnet: Port is not the only port.");
268 } catch (Exception e) {
269 LOG.error("isLastPortinSubnet: isLastPortinSubnet failed due to ", e);
276 public boolean isLastPortinBridge(Node node, OvsdbTerminationPointAugmentation terminationPointAugmentation) {
277 LOG.trace("isLastPortinBridge: for {}", terminationPointAugmentation.getName());
278 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
279 /*Check whether the node has any port other than br-int*/
280 if (terminationPoints != null && !terminationPoints.isEmpty()) {
281 for (TerminationPoint tp : terminationPoints) {
282 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
283 tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
284 if (null != ovsdbTerminationPointAugmentation
285 && !(ovsdbTerminationPointAugmentation.getName().equals(Constants.INTEGRATION_BRIDGE))
286 && !(terminationPointAugmentation.getInterfaceUuid()
287 .equals(ovsdbTerminationPointAugmentation.getInterfaceUuid()))) {
288 LOG.debug("isLastPortinBridge: it the last port in bridge {}",
289 terminationPointAugmentation.getName());
298 public List<Neutron_IPs> getIpAddressList(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
299 if (neutronPortCache == null) {
300 LOG.error("getIpAddress: neutron port is null");
303 LOG.trace("getIpAddress: for {}", terminationPointAugmentation.getName());
304 String neutronPortId = southbound.getInterfaceExternalIdsValue(terminationPointAugmentation,
305 Constants.EXTERNAL_ID_INTERFACE_ID);
306 if (neutronPortId == null) {
309 NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
310 if (neutronPort == null) {
311 LOG.error("getIpAddress: neutron port of {} is not found", neutronPortId);
314 return neutronPort.getFixedIPs();
318 public List<Neutron_IPs> getVmListForSecurityGroup(String portUuid, String securityGroupUuid) {
319 List<Neutron_IPs> vmListForSecurityGroup = new ArrayList<>();
320 /*For every port check whether security grouplist contains the current
323 for (NeutronPort neutronPort:neutronPortCache.getAllPorts()) {
324 if (!neutronPort.getDeviceOwner().contains("compute")) {
325 LOG.debug("getVMListForSecurityGroup : the port {} is not "
326 + "compute port belongs to {}", neutronPort.getID(), neutronPort.getDeviceOwner());
329 if (portUuid.equals(neutronPort.getID())) {
332 List<NeutronSecurityGroup> securityGroups = neutronPort.getSecurityGroups();
333 if (null != securityGroups) {
334 for (NeutronSecurityGroup securityGroup:securityGroups) {
335 if (securityGroup.getSecurityGroupUUID().equals(securityGroupUuid)) {
336 LOG.debug("getVMListForSecurityGroup : adding ports with ips {} "
337 + "compute port", neutronPort.getFixedIPs());
338 if (neutronPort.getFixedIPs() != null) {
339 vmListForSecurityGroup.addAll(neutronPort.getFixedIPs());
346 } catch (Exception e) {
347 LOG.error("getVMListForSecurityGroup: getVMListForSecurityGroup"
348 + " failed due to ", e);
351 return vmListForSecurityGroup;
356 public void syncSecurityGroup(NeutronPort port, List<NeutronSecurityGroup> securityGroupList, boolean write) {
357 LOG.trace("syncSecurityGroup:" + securityGroupList + " Write:" + write);
358 if (null != port && null != port.getSecurityGroups()) {
359 Node node = getNode(port);
363 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
364 if (neutronNetwork == null) {
367 String segmentationId = neutronNetwork.getProviderSegmentationID();
368 OvsdbTerminationPointAugmentation intf = getInterface(node, port);
372 long localPort = southbound.getOFPort(intf);
373 String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
374 if (attachedMac == null) {
375 LOG.debug("programVlanRules: No AttachedMac seen in {}", intf);
378 long dpid = getDpidOfIntegrationBridge(node);
382 String neutronPortId = southbound.getInterfaceExternalIdsValue(intf,
383 Constants.EXTERNAL_ID_INTERFACE_ID);
384 if (neutronPortId == null) {
385 LOG.debug("syncSecurityGroup: No neutronPortId seen in {}", intf);
388 for (NeutronSecurityGroup securityGroupInPort:securityGroupList) {
389 ingressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
390 securityGroupInPort, neutronPortId, write);
391 egressAclProvider.programPortSecurityGroup(dpid, segmentationId, attachedMac, localPort,
392 securityGroupInPort, neutronPortId, write);
398 public void syncSecurityRule(NeutronPort port, NeutronSecurityRule securityRule,Neutron_IPs vmIp, boolean write) {
399 LOG.trace("syncSecurityGroup:" + securityRule + " Write:" + write);
400 if (null != port && null != port.getSecurityGroups()) {
401 Node node = getNode(port);
405 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
406 if (neutronNetwork == null) {
409 String segmentationId = neutronNetwork.getProviderSegmentationID();
410 OvsdbTerminationPointAugmentation intf = getInterface(node, port);
414 long localPort = southbound.getOFPort(intf);
415 String attachedMac = southbound.getInterfaceExternalIdsValue(intf, Constants.EXTERNAL_ID_VM_MAC);
416 if (attachedMac == null) {
417 LOG.debug("programVlanRules: No AttachedMac seen in {}", intf);
420 long dpid = getDpidOfIntegrationBridge(node);
424 if ("IPv4".equals(securityRule.getSecurityRuleEthertype())
425 && "ingress".equals(securityRule.getSecurityRuleDirection())) {
427 ingressAclProvider.programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
428 securityRule, vmIp, write);
429 } else if (securityRule.getSecurityRuleEthertype().equals("IPv4")
430 && securityRule.getSecurityRuleDirection().equals("egress")) {
431 egressAclProvider.programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
432 securityRule, vmIp, write);
437 private long getDpidOfIntegrationBridge(Node node) {
438 LOG.trace("getDpidOfIntegrationBridge:" + node);
440 if (southbound.getBridgeName(node).equals(configurationService.getIntegrationBridgeName())) {
441 dpid = getDpid(node);
444 LOG.warn("getDpidOfIntegerationBridge: dpid not found: {}", node);
449 private long getDpid(Node node) {
450 LOG.trace("getDpid" + node);
451 long dpid = southbound.getDataPathId(node);
453 LOG.warn("getDpid: dpid not found: {}", node);
458 private Node getNode(NeutronPort port) {
459 LOG.trace("getNode:Port" + port);
460 List<Node> toplogyNodes = southbound.readOvsdbTopologyNodes();
462 for (Node topologyNode : toplogyNodes) {
464 Node node = southbound.getBridgeNode(topologyNode,Constants.INTEGRATION_BRIDGE);
465 List<OvsdbTerminationPointAugmentation> ovsdbPorts = southbound.getTerminationPointsOfBridge(node);
466 for (OvsdbTerminationPointAugmentation ovsdbPort : ovsdbPorts) {
467 String uuid = southbound.getInterfaceExternalIdsValue(ovsdbPort,
468 Constants.EXTERNAL_ID_INTERFACE_ID);
469 if (null != uuid && uuid.equals(port.getID())) {
473 } catch (Exception e) {
474 LOG.error("Exception during handlingNeutron network delete", e);
477 LOG.info("no node found for port:" + port);
481 private OvsdbTerminationPointAugmentation getInterface(Node node, NeutronPort port) {
482 LOG.trace("getInterface:Node:" + node + " Port:" + port);
484 List<OvsdbTerminationPointAugmentation> ovsdbPorts = southbound.getTerminationPointsOfBridge(node);
485 for (OvsdbTerminationPointAugmentation ovsdbPort : ovsdbPorts) {
486 String uuid = southbound.getInterfaceExternalIdsValue(ovsdbPort,
487 Constants.EXTERNAL_ID_INTERFACE_ID);
488 if (null != uuid && uuid.equals(port.getID())) {
492 } catch (Exception e) {
493 LOG.error("Exception during handlingNeutron network delete", e);
495 LOG.info("no interface found for node: " + node + " port:" + port);
500 public void setDependencies(ServiceReference serviceReference) {
502 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
503 neutronNetworkCache =
504 (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
505 configurationService =
506 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
510 public void setDependencies(Object impl) {
511 if (impl instanceof INeutronPortCRUD) {
512 neutronPortCache = (INeutronPortCRUD)impl;
513 } else if (impl instanceof INeutronSubnetCRUD) {
514 neutronSubnetCache = (INeutronSubnetCRUD) impl;
515 } else if (impl instanceof IngressAclProvider) {
516 ingressAclProvider = (IngressAclProvider) impl;
517 } else if (impl instanceof EgressAclProvider) {
518 egressAclProvider = (EgressAclProvider) impl;
523 public boolean isConntrackEnabled() {
524 return isConntrackEnabled;