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.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
19 import java.util.concurrent.ExecutionException;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.Router;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.group.NeutronSecurityGroupAware;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
31 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
32 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
33 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
34 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
35 import org.opendaylight.groupbasedpolicy.util.IidFactory;
36 import org.opendaylight.neutron.spi.INeutronPortAware;
37 import org.opendaylight.neutron.spi.NeutronPort;
38 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
39 import org.opendaylight.neutron.spi.NeutronSecurityRule;
40 import org.opendaylight.neutron.spi.Neutron_IPs;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.floating.ip.ports.EndpointByFloatingIpPort;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router._interface.ports.EndpointByRouterInterfacePort;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router.gateway.ports.EndpointByRouterGatewayPort;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.l3.endpoints.ExternalGatewayAsL3Endpoint;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.floating.ip.ports.by.endpoints.FloatingIpPortByEndpoint;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router._interface.ports.by.endpoints.RouterInterfacePortByEndpoint;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router.gateway.ports.by.endpoints.RouterGatewayPortByEndpoint;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
86 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
87 import org.opendaylight.yangtools.yang.common.RpcResult;
88 import org.slf4j.Logger;
89 import org.slf4j.LoggerFactory;
91 import com.google.common.base.Function;
92 import com.google.common.base.Optional;
93 import com.google.common.base.Strings;
94 import com.google.common.collect.Collections2;
95 import com.google.common.collect.ImmutableList;
97 public class NeutronPortAware implements INeutronPortAware {
99 public static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
100 private static final String DEVICE_OWNER_DHCP = "network:dhcp";
101 private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
102 private static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway";
103 private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
104 private final DataBroker dataProvider;
105 private final EndpointService epService;
106 private final NeutronSecurityRuleAware secRuleAware;
107 private final NeutronSecurityGroupAware secGrpAware;
108 private final static Map<String, UniqueId> floatingIpPortByDeviceId = new HashMap<>();
109 private final Set<TenantId> tenantsWithNetworkSeviceEntities = new HashSet<>();
111 public NeutronPortAware(DataBroker dataProvider, EndpointService epService, NeutronSecurityRuleAware secRuleAware, NeutronSecurityGroupAware secGrpAware) {
112 this.dataProvider = checkNotNull(dataProvider);
113 this.epService = checkNotNull(epService);
114 this.secRuleAware = checkNotNull(secRuleAware);
115 this.secGrpAware = secGrpAware;
119 * @see org.opendaylight.neutron.spi.INeutronPortAware#canCreatePort(org.opendaylight.neutron.spi.NeutronPort)
122 public int canCreatePort(NeutronPort port) {
123 LOG.trace("canCreatePort - {}", port);
124 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
125 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
126 if (fixedIPs != null && fixedIPs.size() > 1) {
127 LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
128 return StatusCode.BAD_REQUEST;
130 return StatusCode.OK;
134 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortCreated(org.opendaylight.neutron.spi.NeutronPort)
137 public void neutronPortCreated(NeutronPort port) {
138 LOG.trace("neutronPortCreated - {}", port);
139 if (isRouterInterfacePort(port)) {
140 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
141 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
144 if (isRouterGatewayPort(port)) {
145 LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
146 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
149 if (isFloatingIpPort(port)) {
150 LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
151 floatingIpPortByDeviceId.put(port.getDeviceID(), new UniqueId(port.getID()));
154 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
155 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
156 if (isDhcpPort(port)) {
157 LOG.trace("Port is DHCP port. - {}", port.getID());
158 Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
159 if (firstIp == null) {
160 LOG.warn("Illegal state - DHCP port does not have an IP address.");
164 if (!tenantsWithNetworkSeviceEntities.contains(tenantId)) {
165 tenantsWithNetworkSeviceEntities.add(tenantId);
166 NetworkService.writeNetworkServiceEntitiesToTenant(tenantId, rwTx);
167 NetworkService.writeDhcpClauseWithConsProvEic(tenantId, null, rwTx);
168 NetworkService.writeDnsClauseWithConsProvEic(tenantId, null, rwTx);
169 NetworkClient.writeNetworkClientEntitiesToTenant(tenantId, rwTx);
170 NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.DHCP_CONTRACT_CONSUMER_SELECTOR, rwTx);
171 NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.DNS_CONTRACT_CONSUMER_SELECTOR, rwTx);
174 // this is here b/c stable/kilo sends sec-groups only with port
175 List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
176 if (secGroups != null) {
177 for (NeutronSecurityGroup secGroup : secGroups) {
178 EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
179 Optional<EndpointGroup> potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
180 IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
181 if (!potentialEpg.isPresent()) {
182 boolean isSecGroupCreated = secGrpAware.addNeutronSecurityGroup(secGroup, rwTx);
183 if (!isSecGroupCreated) {
188 List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
189 if (secRules != null) {
190 for (NeutronSecurityRule secRule : secRules) {
191 secRuleAware.addNeutronSecurityRule(secRule, rwTx);
198 boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService);
199 if (!isNeutronPortCreated) {
204 DataStoreHelper.submitToDs(rwTx);
207 public static boolean addNeutronPort(NeutronPort port, ReadWriteTransaction rwTx, EndpointService epService) {
208 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
209 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
210 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
211 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
215 EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
216 addNeutronGbpMapping(port, epKey, rwTx);
219 RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
220 RpcResult<Void> rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
221 if (!rpcResult.isSuccessful()) {
222 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
225 } catch (InterruptedException | ExecutionException e) {
226 LOG.error("addNeutronPort failed. {}", port, e);
232 public static boolean addL3EndpointForExternalGateway(TenantId tenantId, L3ContextId l3ContextId,
233 IpAddress ipAddress, NetworkDomainId networkContainment, ReadWriteTransaction rwTx) {
235 EndpointL3Key epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
236 addNeutronExtGwGbpMapping(epL3Key, rwTx);
237 List<EndpointGroupId> epgIds = new ArrayList<>();
238 // each EP has to be in EPG ANY, except dhcp and router
239 epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
240 epgIds.add(Router.EPG_ID);
241 EndpointL3 epL3 = createL3Endpoint(tenantId, epL3Key, epgIds, networkContainment);
242 InstanceIdentifier<EndpointL3> iid_l3 = IidFactory.l3EndpointIid(l3ContextId, ipAddress);
243 rwTx.put(LogicalDatastoreType.OPERATIONAL, iid_l3, epL3, true);
247 private static void addNeutronExtGwGbpMapping(EndpointL3Key epL3Key, ReadWriteTransaction rwTx) {
248 ExternalGatewayAsL3Endpoint externalGatewayL3Endpoint = MappingFactory.createExternalGatewayByL3Endpoint(epL3Key);
249 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()),
250 externalGatewayL3Endpoint, true);
253 private static void addNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
254 UniqueId portId = new UniqueId(port.getID());
255 if (isRouterInterfacePort(port)) {
256 LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
257 EndpointByRouterInterfacePort endpointByPort = MappingFactory.createEndpointByRouterInterfacePort(epKey,
259 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterInterfacePortIid(portId),
260 endpointByPort, true);
261 RouterInterfacePortByEndpoint portByEndpoint = MappingFactory.createRouterInterfacePortByEndpoint(portId,
263 rwTx.put(LogicalDatastoreType.OPERATIONAL,
264 NeutronGbpIidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
265 portByEndpoint, true);
266 } else if (isRouterGatewayPort(port)) {
267 LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
268 EndpointByRouterGatewayPort endpointByPort = MappingFactory.createEndpointByRouterGatewayPort(epKey, portId);
269 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterGatewayPortIid(portId),
270 endpointByPort, true);
271 RouterGatewayPortByEndpoint portByEndpoint = MappingFactory.createRouterGatewayPortByEndpoint(portId, epKey);
272 rwTx.put(LogicalDatastoreType.OPERATIONAL,
273 NeutronGbpIidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
274 portByEndpoint, true);
275 } else if (isFloatingIpPort(port)) {
276 LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
277 EndpointByFloatingIpPort endpointByPort = MappingFactory.createEndpointByFloatingIpPort(epKey, portId);
278 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByFloatingIpPortIid(portId),
279 endpointByPort, true);
280 FloatingIpPortByEndpoint portByEndpoint = MappingFactory.createFloatingIpPortByEndpoint(portId, epKey);
281 rwTx.put(LogicalDatastoreType.OPERATIONAL,
282 NeutronGbpIidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
283 portByEndpoint, true);
285 LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
286 port.getDeviceOwner(), epKey);
287 EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
288 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort, true);
289 PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
290 rwTx.put(LogicalDatastoreType.OPERATIONAL,
291 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint, true);
295 public static boolean addL3PrefixEndpoint(L3ContextId l3ContextId, IpPrefix ipPrefix, IpAddress ipAddress, TenantId tenantId,
296 EndpointService epService) {
297 EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey( ipPrefix, l3ContextId);
298 EndpointL3Key epL3Key = null;
299 List<EndpointL3Key> l3Gateways = new ArrayList<>();
300 if (ipAddress != null) {
301 epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
302 l3Gateways.add(epL3Key);
305 RegisterL3PrefixEndpointInput registerL3PrefixEpRpcInput = createRegisterL3PrefixEndpointInput(epL3PrefixKey, l3Gateways,tenantId);
307 RpcResult<Void> rpcResult = epService.registerL3PrefixEndpoint(registerL3PrefixEpRpcInput).get();
308 if (!rpcResult.isSuccessful()) {
309 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerL3PrefixEpRpcInput);
312 } catch (InterruptedException | ExecutionException e) {
313 LOG.error("addPort - RPC invocation failed.", e);
320 private static boolean validateForwardingCtx(ForwardingCtx fwCtx) {
321 if (fwCtx.getL2FloodDomain() == null) {
322 LOG.warn("Illegal state - l2-flood-domain does not exist.");
325 if (fwCtx.getL2BridgeDomain() == null) {
326 LOG.warn("Illegal state - l2-bridge-domain does not exist.");
329 if (fwCtx.getL3Context() == null) {
330 LOG.warn("Illegal state - l3-context does not exist.");
337 * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort,
338 * org.opendaylight.neutron.spi.NeutronPort)
341 public int canUpdatePort(NeutronPort delta, NeutronPort original) {
342 LOG.trace("canUpdatePort - delta: {} original: {}", delta, original);
343 if (delta.getFixedIPs() == null || delta.getFixedIPs().isEmpty()) {
344 return StatusCode.OK;
346 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
347 List<Neutron_IPs> fixedIPs = delta.getFixedIPs();
348 if (fixedIPs != null && fixedIPs.size() > 1) {
349 LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
350 return StatusCode.BAD_REQUEST;
352 return StatusCode.OK;
356 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortUpdated(org.opendaylight.neutron.spi.NeutronPort)
359 public void neutronPortUpdated(NeutronPort port) {
360 LOG.trace("neutronPortUpdated - {}", port);
361 if (isRouterInterfacePort(port)) {
362 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
363 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
366 if (isRouterGatewayPort(port)) {
367 LOG.trace("Port is router gateway - {}", port.getID());
370 if (isFloatingIpPort(port)) {
371 LOG.trace("Port is floating ip - {}", port.getID());
374 if (Strings.isNullOrEmpty(port.getTenantID())) {
375 LOG.trace("REMOVE ME: Tenant is null - {}", port.getID());
379 ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
380 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
381 MacAddress macAddress = new MacAddress(port.getMacAddress());
382 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
383 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
384 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
390 Optional<Endpoint> potentionalEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
391 IidFactory.endpointIid(fwCtx.getL2BridgeDomain().getId(), macAddress), rTx);
392 if (!potentionalEp.isPresent()) {
393 LOG.warn("Illegal state - endpoint {} does not exist.", new EndpointKey(fwCtx.getL2BridgeDomain().getId(),
399 Endpoint ep = potentionalEp.get();
400 if (isEpIpDifferentThanPortFixedIp(ep, port) || isEpgDifferentThanSecGrp(ep, port)) {
401 UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(ep);
402 RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
404 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
405 if (!rpcResult.isSuccessful()) {
406 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
410 rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
411 if (!rpcResult.isSuccessful()) {
412 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
416 } catch (InterruptedException | ExecutionException e) {
417 LOG.error("addPort - RPC invocation failed.", e);
425 private boolean isEpIpDifferentThanPortFixedIp(Endpoint ep, NeutronPort port) {
426 List<L3Address> l3Addresses = ep.getL3Address();
427 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
428 if ((l3Addresses == null || l3Addresses.isEmpty()) && (fixedIPs == null || fixedIPs.isEmpty())) {
431 if (l3Addresses != null && !l3Addresses.isEmpty() && fixedIPs != null && !fixedIPs.isEmpty()) {
432 if (fixedIPs.get(0).getIpAddress().equals(Utils.getStringIpAddress(l3Addresses.get(0).getIpAddress()))) {
439 private boolean isEpgDifferentThanSecGrp(Endpoint ep, NeutronPort port) {
440 List<EndpointGroupId> epgIds = ep.getEndpointGroups();
441 List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
442 if ((epgIds == null || epgIds.isEmpty()) && (secGroups == null || secGroups.isEmpty())) {
445 if (epgIds != null && !epgIds.isEmpty() && secGroups != null && !secGroups.isEmpty()) {
446 if (epgIds.size() != secGroups.size()) {
449 Collection<EndpointGroupId> epgIdsFromSecGroups = Collections2.transform(secGroups,
450 new Function<NeutronSecurityGroup, EndpointGroupId>() {
453 public EndpointGroupId apply(NeutronSecurityGroup input) {
454 return new EndpointGroupId(input.getSecurityGroupUUID());
457 // order independent equals
458 Set<EndpointGroupId> one = new HashSet<>(epgIds);
459 Set<EndpointGroupId> two = new HashSet<>(epgIdsFromSecGroups);
460 if (one.equals(two)) {
468 * @see org.opendaylight.neutron.spi.INeutronPortAware#canDeletePort(org.opendaylight.neutron.spi.NeutronPort)
471 public int canDeletePort(NeutronPort port) {
472 LOG.trace("canDeletePort - {}", port);
473 // nothing to consider
474 return StatusCode.OK;
478 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortDeleted(org.opendaylight.neutron.spi.NeutronPort)
481 public void neutronPortDeleted(NeutronPort port) {
482 LOG.trace("neutronPortDeleted - {}", port);
483 if (isRouterInterfacePort(port)) {
484 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
485 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
488 if (isRouterGatewayPort(port)) {
489 LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
490 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
493 if (isFloatingIpPort(port)) {
494 LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
495 floatingIpPortByDeviceId.remove(port.getDeviceID());
497 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
498 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
499 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
500 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
501 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
507 EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
508 deleteNeutronGbpMapping(port, epKey, rwTx);
509 UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
511 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
512 if (!rpcResult.isSuccessful()) {
513 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
515 } catch (InterruptedException | ExecutionException e) {
516 LOG.error("addPort - RPC invocation failed.", e);
521 private static void deleteNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
522 UniqueId portId = new UniqueId(port.getID());
523 if (isRouterInterfacePort(port)) {
524 LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
525 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
526 NeutronGbpIidFactory.endpointByRouterInterfacePortIid(portId), rwTx);
527 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
528 NeutronGbpIidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
529 } else if (isRouterGatewayPort(port)) {
530 LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
531 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
532 NeutronGbpIidFactory.endpointByRouterGatewayPortIid(portId), rwTx);
533 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
534 NeutronGbpIidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
535 } else if (isFloatingIpPort(port)) {
536 LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
537 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
538 NeutronGbpIidFactory.endpointByFloatingIpPortIid(portId), rwTx);
539 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
540 NeutronGbpIidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
542 LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
543 port.getDeviceOwner(), epKey);
544 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), rwTx);
545 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
546 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
550 private static RegisterL3PrefixEndpointInput createRegisterL3PrefixEndpointInput(EndpointL3PrefixKey key, List<EndpointL3Key> endpointL3Keys, TenantId tenantId) {
551 List<EndpointGroupId> epgIds = new ArrayList<>();
552 List<EndpointL3Gateways> l3Gateways = new ArrayList<EndpointL3Gateways>();
553 for (EndpointL3Key epL3Key : endpointL3Keys) {
554 EndpointL3Gateways l3Gateway = new EndpointL3GatewaysBuilder().setIpAddress(epL3Key.getIpAddress())
555 .setL3Context(epL3Key.getL3Context())
557 l3Gateways.add(l3Gateway);
559 RegisterL3PrefixEndpointInputBuilder inputBuilder = new RegisterL3PrefixEndpointInputBuilder()
560 .setL3Context(key.getL3Context())
561 .setIpPrefix(key.getIpPrefix())
562 .setEndpointGroups(epgIds)
564 .setEndpointL3Gateways(l3Gateways)
565 .setTimestamp(System.currentTimeMillis());
566 return inputBuilder.build();
569 private static EndpointL3 createL3Endpoint(TenantId tenantId, EndpointL3Key epL3Key,
570 List<EndpointGroupId> epgIds, NetworkDomainId containment) {
572 EndpointL3Builder epL3Builder = new EndpointL3Builder()
574 .setNetworkContainment(containment)
575 .setIpAddress(epL3Key.getIpAddress())
576 .setL3Context(epL3Key.getL3Context())
577 .setEndpointGroups(epgIds)
578 .setTimestamp(System.currentTimeMillis());
580 return epL3Builder.build();
583 private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
584 List<EndpointGroupId> epgIds = new ArrayList<>();
585 if (isDhcpPort(port)) {
586 epgIds.add(NetworkService.EPG_ID);
589 List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
590 if ((securityGroups == null || securityGroups.isEmpty())) {
591 if (isFloatingIpPort(port)) {
592 epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
593 } else if (!isDhcpPort(port)) {
595 "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
599 for (NeutronSecurityGroup secGrp : securityGroups) {
600 epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID()));
602 epgIds.add(NetworkClient.EPG_ID);
604 LocationType locationType = LocationType.Internal;
605 if(isRouterGatewayPort(port)) {
606 locationType = LocationType.External;
608 RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context(
609 fwCtx.getL2BridgeDomain().getId())
610 .setMacAddress(new MacAddress(port.getMacAddress()))
611 .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID())))
612 .setEndpointGroups(epgIds)
613 .addAugmentation(OfOverlayContextInput.class,
614 new OfOverlayContextInputBuilder()
615 .setPortName(createTapPortName(port))
616 .setLocationType(locationType)
618 .setTimestamp(System.currentTimeMillis());
619 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
620 // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer
621 // will support l3-endpoints. Then we will register L2 and L3 endpoints separately.
622 Neutron_IPs firstIp = MappingUtils.getFirstIp(fixedIPs);
623 if (firstIp != null) {
624 inputBuilder.setNetworkContainment(new SubnetId(firstIp.getSubnetUUID()));
625 L3Address l3Address = new L3AddressBuilder().setIpAddress(Utils.createIpAddress(firstIp.getIpAddress()))
626 .setL3Context(fwCtx.getL3Context().getId())
628 inputBuilder.setL3Address(ImmutableList.of(l3Address));
630 if (!Strings.isNullOrEmpty(port.getName())) {
633 return inputBuilder.build();
636 private static Name createTapPortName(NeutronPort port) {
637 return new Name("tap" + port.getID().substring(0, 11));
640 private static boolean isDhcpPort(NeutronPort port) {
641 return DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
644 private static boolean isRouterInterfacePort(NeutronPort port) {
645 return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner());
648 private static boolean isRouterGatewayPort(NeutronPort port) {
649 return DEVICE_OWNER_ROUTER_GATEWAY.equals(port.getDeviceOwner());
652 private static boolean isFloatingIpPort(NeutronPort port) {
653 return DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner());
656 private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) {
657 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
658 L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build();
659 inputBuilder.setL2(ImmutableList.of(l2Ep));
660 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
661 // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
662 // be registered separately.
663 if (ep.getL3Address() != null && !ep.getL3Address().isEmpty()) {
664 List<L3> l3Eps = new ArrayList<>();
665 for (L3Address ip : ep.getL3Address()) {
666 l3Eps.add(new L3Builder().setL3Context(ip.getL3Context()).setIpAddress(ip.getIpAddress()).build());
668 inputBuilder.setL3(l3Eps);
670 return inputBuilder.build();
673 private UnregisterEndpointInput createUnregisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
674 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
675 L2 l2Ep = new L2Builder().setL2Context(fwCtx.getL2BridgeDomain().getId())
676 .setMacAddress(new MacAddress(port.getMacAddress()))
678 inputBuilder.setL2(ImmutableList.of(l2Ep));
679 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
680 // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
681 // be registered separately.
682 if (port.getFixedIPs() != null && !port.getFixedIPs().isEmpty()) {
683 inputBuilder.setL3(createL3s(port.getFixedIPs(), fwCtx.getL3Context().getId()));
685 return inputBuilder.build();
688 private List<L3> createL3s(List<Neutron_IPs> neutronIps, L3ContextId l3ContextId) {
689 List<L3> l3s = new ArrayList<>();
690 for (Neutron_IPs fixedIp : neutronIps) {
691 String ip = fixedIp.getIpAddress();
692 L3 l3 = new L3Builder().setIpAddress(Utils.createIpAddress(ip)).setL3Context(l3ContextId).build();
698 public static UniqueId getFloatingIpPortIdByDeviceId(String deviceId) {
699 return floatingIpPortByDeviceId.get(deviceId);