2 * Copyright (c) 2015 Cisco Systems, 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
8 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
10 import static com.google.common.base.Preconditions.checkNotNull;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.HashSet;
15 import java.util.List;
17 import java.util.concurrent.ExecutionException;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
21 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
30 import org.opendaylight.neutron.spi.INeutronPortAware;
31 import org.opendaylight.neutron.spi.NeutronPort;
32 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
33 import org.opendaylight.neutron.spi.NeutronSecurityRule;
34 import org.opendaylight.neutron.spi.Neutron_IPs;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInputBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router._interface.ports.EndpointByRouterInterfacePort;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router.gateway.ports.EndpointByRouterGatewayPort;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router._interface.ports.by.endpoints.RouterInterfacePortByEndpoint;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router.gateway.ports.by.endpoints.RouterGatewayPortByEndpoint;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
76 import org.opendaylight.yangtools.yang.common.RpcResult;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
80 import com.google.common.base.Function;
81 import com.google.common.base.Optional;
82 import com.google.common.base.Strings;
83 import com.google.common.collect.Collections2;
84 import com.google.common.collect.ImmutableList;
86 public class NeutronPortAware implements INeutronPortAware {
88 public static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
89 private static final String DEVICE_OWNER_DHCP = "network:dhcp";
90 private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
91 private static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway";
92 private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
93 private static final int DHCP_CLIENT_PORT = 68;
94 private static final int DHCP_SERVER_PORT = 67;
95 private final DataBroker dataProvider;
96 private final EndpointService epService;
98 public NeutronPortAware(DataBroker dataProvider, EndpointService epService) {
99 this.dataProvider = checkNotNull(dataProvider);
100 this.epService = checkNotNull(epService);
104 * @see org.opendaylight.neutron.spi.INeutronPortAware#canCreatePort(org.opendaylight.neutron.spi.NeutronPort)
107 public int canCreatePort(NeutronPort port) {
108 LOG.trace("canCreatePort - {}", port);
109 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
110 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
111 if (fixedIPs != null && fixedIPs.size() > 1) {
112 LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
113 return StatusCode.BAD_REQUEST;
115 return StatusCode.OK;
119 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortCreated(org.opendaylight.neutron.spi.NeutronPort)
122 public void neutronPortCreated(NeutronPort port) {
123 LOG.trace("neutronPortCreated - {}", port);
124 if (isRouterInterfacePort(port)) {
125 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
126 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
129 if (isRouterGatewayPort(port)) {
130 LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
131 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
134 if (isFloatingIp(port)) {
135 LOG.trace("Port is floating ip - {}", port.getID());
138 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
139 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
140 if (isDhcpPort(port)) {
141 LOG.trace("Port is DHCP port. - {}", port.getID());
142 List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, null, rwTx);
143 if (dhcpSecRules == null) {
148 for (NeutronSecurityRule dhcpSecRule : dhcpSecRules) {
149 boolean isDhcpSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(dhcpSecRule, rwTx);
150 if (!isDhcpSecRuleAdded) {
156 List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
157 if (secGroups != null) {
158 for (NeutronSecurityGroup secGroup : secGroups) {
159 EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
160 Optional<EndpointGroup> potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
161 IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
162 if (!potentialEpg.isPresent()) {
163 boolean isSecGroupCreated = NeutronSecurityGroupAware.addNeutronSecurityGroup(secGroup, rwTx);
164 if (!isSecGroupCreated) {
168 if (containsSecRuleWithRemoteSecGroup(secGroup)) {
169 List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, epgId, rwTx);
170 if (dhcpSecRules == null) {
174 List<NeutronSecurityRule> routerSecRules = NeutronRouterAware.createRouterSecRules(port, epgId, rwTx);
175 if (routerSecRules == null) {
181 List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
182 if (secRules != null) {
183 for (NeutronSecurityRule secRule : secRules) {
184 NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx);
191 boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService);
192 if (!isNeutronPortCreated) {
197 DataStoreHelper.submitToDs(rwTx);
200 public static boolean addNeutronPort(NeutronPort port, ReadWriteTransaction rwTx, EndpointService epService) {
201 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
202 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
203 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
204 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
208 EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
209 addNeutronGbpMapping(port, epKey, rwTx);
212 RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
214 RpcResult<Void> rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
215 if (!rpcResult.isSuccessful()) {
216 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
219 } catch (InterruptedException | ExecutionException e) {
220 LOG.error("addPort - RPC invocation failed.", e);
226 private static void addNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
227 if (isRouterInterfacePort(port)) {
228 LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
229 UniqueId portId = new UniqueId(port.getID());
230 EndpointByRouterInterfacePort endpointByPort = MappingFactory.createEndpointByRouterInterfacePort(epKey,
232 rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByRouterInterfacePortIid(portId),
233 endpointByPort, true);
234 RouterInterfacePortByEndpoint portByEndpoint = MappingFactory.createRouterInterfacePortByEndpoint(portId,
236 rwTx.put(LogicalDatastoreType.OPERATIONAL,
237 IidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
238 portByEndpoint, true);
239 } else if (isRouterGatewayPort(port)) {
240 LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
241 UniqueId portId = new UniqueId(port.getID());
242 EndpointByRouterGatewayPort endpointByPort = MappingFactory.createEndpointByRouterGatewayPort(epKey, portId);
243 rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByRouterGatewayPortIid(portId),
244 endpointByPort, true);
245 RouterGatewayPortByEndpoint portByEndpoint = MappingFactory.createRouterGatewayPortByEndpoint(portId, epKey);
246 rwTx.put(LogicalDatastoreType.OPERATIONAL,
247 IidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
248 portByEndpoint, true);
250 LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
251 port.getDeviceOwner(), epKey);
252 UniqueId portId = new UniqueId(port.getID());
253 EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
254 rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByPortIid(portId), endpointByPort, true);
255 PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
256 rwTx.put(LogicalDatastoreType.OPERATIONAL,
257 IidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint, true);
261 public static boolean addL3PrefixEndpoint(L3ContextId l3ContextId, IpPrefix ipPrefix, IpAddress ipAddress, TenantId tenantId,
262 ReadWriteTransaction rwTx, EndpointService epService) {
264 EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey( ipPrefix, l3ContextId);
266 EndpointL3Key epL3Key = null;
267 List<EndpointL3Key> l3Gateways = new ArrayList<>();
268 if (ipAddress != null) {
269 epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
270 l3Gateways.add(epL3Key);
275 RegisterL3PrefixEndpointInput registerL3PrefixEpRpcInput = createRegisterL3PrefixEndpointInput(epL3PrefixKey, l3Gateways,tenantId);
277 RpcResult<Void> rpcResult = epService.registerL3PrefixEndpoint(registerL3PrefixEpRpcInput).get();
278 if (!rpcResult.isSuccessful()) {
279 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerL3PrefixEpRpcInput);
282 } catch (InterruptedException | ExecutionException e) {
283 LOG.error("addPort - RPC invocation failed.", e);
290 private static boolean validateForwardingCtx(ForwardingCtx fwCtx) {
291 if (fwCtx.getL2FloodDomain() == null) {
292 LOG.warn("Illegal state - l2-flood-domain does not exist.");
295 if (fwCtx.getL2BridgeDomain() == null) {
296 LOG.warn("Illegal state - l2-bridge-domain does not exist.");
299 if (fwCtx.getL3Context() == null) {
300 LOG.warn("Illegal state - l3-context does not exist.");
306 private List<NeutronSecurityRule> createDhcpSecRules(NeutronPort port, EndpointGroupId consumerEpgId, ReadTransaction rTx) {
307 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
308 Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
309 if (firstIp == null) {
310 LOG.warn("Illegal state - DHCP port does not have an IP address.");
313 SubnetId dhcpSubnetId = new SubnetId(firstIp.getSubnetUUID());
314 Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
315 IidFactory.subnetIid(tenantId, dhcpSubnetId), rTx);
316 if (!potentialSubnet.isPresent()) {
317 LOG.warn("Illegal state - Subnet {} where is DHCP port does not exist.", dhcpSubnetId.getValue());
320 IpPrefix ipSubnet = potentialSubnet.get().getIpPrefix();
321 NeutronSecurityRule dhcpRuleEgress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, true);
322 NeutronSecurityRule dhcpRuleIngress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, false);
323 return ImmutableList.of(dhcpRuleEgress, dhcpRuleIngress);
326 private NeutronSecurityRule createDhcpSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId,
328 NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
329 dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
330 dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
331 dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
332 if (consumerEpgId != null) {
333 dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
336 dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid);
337 dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
338 dhcpSecRule.setSecurityRulePortMin(DHCP_CLIENT_PORT);
339 dhcpSecRule.setSecurityRulePortMax(DHCP_CLIENT_PORT);
341 dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid);
342 dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
343 dhcpSecRule.setSecurityRulePortMin(DHCP_SERVER_PORT);
344 dhcpSecRule.setSecurityRulePortMax(DHCP_SERVER_PORT);
346 dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
347 if (ipSubnet.getIpv4Prefix() != null) {
348 dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
350 dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
356 * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort,
357 * org.opendaylight.neutron.spi.NeutronPort)
360 public int canUpdatePort(NeutronPort delta, NeutronPort original) {
361 LOG.trace("canUpdatePort - delta: {} original: {}", delta, original);
362 if (delta.getFixedIPs() == null || delta.getFixedIPs().isEmpty()) {
363 return StatusCode.OK;
365 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
366 List<Neutron_IPs> fixedIPs = delta.getFixedIPs();
367 if (fixedIPs != null && fixedIPs.size() > 1) {
368 LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
369 return StatusCode.BAD_REQUEST;
371 return StatusCode.OK;
375 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortUpdated(org.opendaylight.neutron.spi.NeutronPort)
378 public void neutronPortUpdated(NeutronPort port) {
379 LOG.trace("neutronPortUpdated - {}", port);
380 if (isRouterInterfacePort(port)) {
381 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
382 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
385 if (isRouterGatewayPort(port)) {
386 LOG.trace("Port is router gateway - {}", port.getID());
389 if (isFloatingIp(port)) {
390 LOG.trace("Port is floating ip - {}", port.getID());
393 if (Strings.isNullOrEmpty(port.getTenantID())) {
394 LOG.trace("REMOVE ME: Tenant is null - {}", port.getID());
398 ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
399 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
400 MacAddress macAddress = new MacAddress(port.getMacAddress());
401 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
402 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
403 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
409 Optional<Endpoint> potentionalEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
410 IidFactory.endpointIid(fwCtx.getL2BridgeDomain().getId(), macAddress), rTx);
411 if (!potentionalEp.isPresent()) {
412 LOG.warn("Illegal state - endpoint {} does not exist.", new EndpointKey(fwCtx.getL2BridgeDomain().getId(),
418 Endpoint ep = potentionalEp.get();
419 if (isEpIpDifferentThanPortFixedIp(ep, port) || isEpgDifferentThanSecGrp(ep, port)) {
420 UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(ep);
421 RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
423 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
424 if (!rpcResult.isSuccessful()) {
425 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
429 rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
430 if (!rpcResult.isSuccessful()) {
431 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
435 } catch (InterruptedException | ExecutionException e) {
436 LOG.error("addPort - RPC invocation failed.", e);
444 private boolean isEpIpDifferentThanPortFixedIp(Endpoint ep, NeutronPort port) {
445 List<L3Address> l3Addresses = ep.getL3Address();
446 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
447 if ((l3Addresses == null || l3Addresses.isEmpty()) && (fixedIPs == null || fixedIPs.isEmpty())) {
450 if (l3Addresses != null && !l3Addresses.isEmpty() && fixedIPs != null && !fixedIPs.isEmpty()) {
451 if (fixedIPs.get(0).getIpAddress().equals(Utils.getStringIpAddress(l3Addresses.get(0).getIpAddress()))) {
458 private boolean isEpgDifferentThanSecGrp(Endpoint ep, NeutronPort port) {
459 List<EndpointGroupId> epgIds = ep.getEndpointGroups();
460 List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
461 if ((epgIds == null || epgIds.isEmpty()) && (secGroups == null || secGroups.isEmpty())) {
464 if (epgIds != null && !epgIds.isEmpty() && secGroups != null && !secGroups.isEmpty()) {
465 if (epgIds.size() != secGroups.size()) {
468 Collection<EndpointGroupId> epgIdsFromSecGroups = Collections2.transform(secGroups,
469 new Function<NeutronSecurityGroup, EndpointGroupId>() {
472 public EndpointGroupId apply(NeutronSecurityGroup input) {
473 return new EndpointGroupId(input.getSecurityGroupUUID());
476 // order independent equals
477 Set<EndpointGroupId> one = new HashSet<>(epgIds);
478 Set<EndpointGroupId> two = new HashSet<>(epgIdsFromSecGroups);
479 if (one.equals(two)) {
487 * @see org.opendaylight.neutron.spi.INeutronPortAware#canDeletePort(org.opendaylight.neutron.spi.NeutronPort)
490 public int canDeletePort(NeutronPort port) {
491 LOG.trace("canDeletePort - {}", port);
492 // nothing to consider
493 return StatusCode.OK;
497 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortDeleted(org.opendaylight.neutron.spi.NeutronPort)
500 public void neutronPortDeleted(NeutronPort port) {
501 LOG.trace("neutronPortDeleted - {}", port);
502 if (isRouterInterfacePort(port)) {
503 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
504 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
507 ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
508 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
509 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
510 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
511 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
517 UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
519 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
520 if (!rpcResult.isSuccessful()) {
521 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
523 } catch (InterruptedException | ExecutionException e) {
524 LOG.error("addPort - RPC invocation failed.", e);
530 private static RegisterL3PrefixEndpointInput createRegisterL3PrefixEndpointInput(EndpointL3PrefixKey key, List<EndpointL3Key> endpointL3Keys, TenantId tenantId) {
531 List<EndpointGroupId> epgIds = new ArrayList<>();
532 // each EP has to be in EPG ANY, except dhcp and router
533 epgIds.add(MappingUtils.EPG_ANY_ID);
535 List<EndpointL3Gateways> l3Gateways = new ArrayList<EndpointL3Gateways>();
536 for (EndpointL3Key epL3Key : endpointL3Keys) {
537 EndpointL3Gateways l3Gateway = new EndpointL3GatewaysBuilder().setIpAddress(epL3Key.getIpAddress())
538 .setL3Context(epL3Key.getL3Context())
540 l3Gateways.add(l3Gateway);
542 RegisterL3PrefixEndpointInputBuilder inputBuilder = new RegisterL3PrefixEndpointInputBuilder()
543 .setL3Context(key.getL3Context())
544 .setIpPrefix(key.getIpPrefix())
545 .setEndpointGroups(epgIds)
547 .setEndpointL3Gateways(l3Gateways)
548 .setTimestamp(System.currentTimeMillis());
549 return inputBuilder.build();
552 private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
553 List<EndpointGroupId> epgIds = new ArrayList<>();
554 // each EP has to be in EPG ANY, except dhcp and router
555 if (isDhcpPort(port)) {
556 epgIds.add(MappingUtils.EPG_DHCP_ID);
557 } else if (!containsSecRuleWithRemoteSecGroup(port.getSecurityGroups())) {
558 epgIds.add(MappingUtils.EPG_ANY_ID);
561 List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
562 if ((securityGroups == null || securityGroups.isEmpty())) {
563 if (!isDhcpPort(port)) {
565 "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
569 for (NeutronSecurityGroup secGrp : securityGroups) {
570 epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID()));
573 LocationType locationType = LocationType.Internal;
574 if(isRouterGatewayPort(port)) {
575 locationType = LocationType.External;
577 RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context(
578 fwCtx.getL2BridgeDomain().getId())
579 .setMacAddress(new MacAddress(port.getMacAddress()))
580 .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID())))
581 .setEndpointGroups(epgIds)
582 .addAugmentation(OfOverlayContextInput.class,
583 new OfOverlayContextInputBuilder()
584 .setPortName(createTapPortName(port))
585 .setLocationType(locationType)
587 .setTimestamp(System.currentTimeMillis());
588 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
589 // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer
590 // will support l3-endpoints. Then we will register L2 and L3 endpoints separately.
591 Neutron_IPs firstIp = MappingUtils.getFirstIp(fixedIPs);
592 if (firstIp != null) {
593 inputBuilder.setNetworkContainment(new SubnetId(firstIp.getSubnetUUID()));
594 L3Address l3Address = new L3AddressBuilder().setIpAddress(Utils.createIpAddress(firstIp.getIpAddress()))
595 .setL3Context(fwCtx.getL3Context().getId())
597 inputBuilder.setL3Address(ImmutableList.of(l3Address));
599 if (!Strings.isNullOrEmpty(port.getName())) {
602 return inputBuilder.build();
605 private static boolean containsSecRuleWithRemoteSecGroup(List<NeutronSecurityGroup> secGroups) {
606 if (secGroups == null) {
609 for (NeutronSecurityGroup secGroup : secGroups) {
610 boolean containsSecRuleWithRemoteSecGroup = containsSecRuleWithRemoteSecGroup(secGroup);
611 if (containsSecRuleWithRemoteSecGroup) {
618 private static boolean containsSecRuleWithRemoteSecGroup(NeutronSecurityGroup secGroup) {
619 List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
620 if (secRules == null) {
623 for (NeutronSecurityRule secRule : secRules) {
624 if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
631 private static Name createTapPortName(NeutronPort port) {
632 return new Name("tap" + port.getID().substring(0, 11));
635 private static boolean isDhcpPort(NeutronPort port) {
636 return DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
639 private static boolean isRouterInterfacePort(NeutronPort port) {
640 return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner());
643 private static boolean isRouterGatewayPort(NeutronPort port) {
644 return DEVICE_OWNER_ROUTER_GATEWAY.equals(port.getDeviceOwner());
647 private static boolean isFloatingIp(NeutronPort port) {
648 return DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner());
651 private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) {
652 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
653 L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build();
654 inputBuilder.setL2(ImmutableList.of(l2Ep));
655 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
656 // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
657 // be registered separately.
658 if (ep.getL3Address() != null && !ep.getL3Address().isEmpty()) {
659 List<L3> l3Eps = new ArrayList<>();
660 for (L3Address ip : ep.getL3Address()) {
661 l3Eps.add(new L3Builder().setL3Context(ip.getL3Context()).setIpAddress(ip.getIpAddress()).build());
663 inputBuilder.setL3(l3Eps);
665 return inputBuilder.build();
668 private UnregisterEndpointInput createUnregisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
669 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
670 L2 l2Ep = new L2Builder().setL2Context(fwCtx.getL2BridgeDomain().getId())
671 .setMacAddress(new MacAddress(port.getMacAddress()))
673 inputBuilder.setL2(ImmutableList.of(l2Ep));
674 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
675 // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
676 // be registered separately.
677 if (port.getFixedIPs() != null && !port.getFixedIPs().isEmpty()) {
678 inputBuilder.setL3(createL3s(port.getFixedIPs(), fwCtx.getL3Context().getId()));
680 return inputBuilder.build();
683 private List<L3> createL3s(List<Neutron_IPs> neutronIps, L3ContextId l3ContextId) {
684 List<L3> l3s = new ArrayList<>();
685 for (Neutron_IPs fixedIp : neutronIps) {
686 String ip = fixedIp.getIpAddress();
687 L3 l3 = new L3Builder().setIpAddress(Utils.createIpAddress(ip)).setL3Context(l3ContextId).build();