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 com.google.common.base.Optional;
13 import com.google.common.collect.ImmutableList;
14 import com.google.common.collect.Lists;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
20 import java.util.stream.Collectors;
22 import javax.annotation.Nullable;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
29 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
31 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.MetadataService;
32 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
33 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
34 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
35 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
36 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils;
37 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
38 import org.opendaylight.groupbasedpolicy.util.IidFactory;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpoint;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpointKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
96 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
97 import org.slf4j.Logger;
98 import org.slf4j.LoggerFactory;
100 public class NeutronPortAware implements NeutronAware<Port> {
102 private static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
103 public static final InstanceIdentifier<Port> PORT_WILDCARD_IID =
104 InstanceIdentifier.builder(Neutron.class).child(Ports.class).child(Port.class).build();
105 private final DataBroker dataProvider;
106 private final EndpointRegistrator epRegistrator;
107 private final IpPrefix metadataIpPrefix;
109 public NeutronPortAware(DataBroker dataProvider, EndpointRegistrator epRegistrator,
110 @Nullable IpPrefix metadataIpPrefix) {
111 this.dataProvider = checkNotNull(dataProvider);
112 this.epRegistrator = checkNotNull(epRegistrator);
113 this.metadataIpPrefix = checkNotNull(metadataIpPrefix);
117 public void onCreated(Port createdItem, Neutron neutron) {
118 onCreated(createdItem, neutron, true);
121 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
122 // this will be removed when deprecated classes will be cleared.
123 public void onCreated(Port port, Neutron neutron, boolean addBaseEpMapping) {
124 LOG.trace("created port - {}", port);
125 if (PortUtils.isRouterInterfacePort(port)) {
126 LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
127 // router interface port can have only one IP
128 Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
129 if (!potentialPortIpWithSubnet.isPresent()) {
130 LOG.warn("Illegal state - router interface port does not contain fixed IPs {}", port);
133 final FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
134 final ContextId routerL3Context = new ContextId(port.getDeviceId());
135 AddressEndpointKey addrEpKey = new AddressEndpointKey(port.getMacAddress().getValue(), MacAddressType.class,
136 new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
137 UniqueId portId = new UniqueId(port.getUuid().getValue());
138 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
139 addBaseEndpointMappings(addrEpKey, portId, rwTx);
140 // Add Qrouter and VPProuter port as Endpoint
141 if (port.getAugmentation(PortBindingExtension.class) != null && PortUtils.DEVICE_VIF_TYPE
142 .equals(port.getAugmentation(PortBindingExtension.class).getVifType())) {
143 LOG.trace("Port is QRouter port: {}", port.getUuid().getValue());
144 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
145 if (!firstFixedIps.isPresent()) {
146 LOG.warn("QRouter port does not have an IP address. {}", port);
149 FixedIps ipWithSubnet = firstFixedIps.get();
150 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
151 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
152 epgsFromSecGroups.add(NetworkService.EPG_ID);
153 // BUILD BASE ENDPOINT
154 AddressEndpointRegBuilder l2BaseEp =
155 createBasicMacAddrEpInputBuilder(port, networkContainment, epgsFromSecGroups);
156 AddressEndpointRegBuilder l3BaseEp =
157 createBasicL3AddrEpInputBuilder(port, networkContainment, epgsFromSecGroups, neutron);
158 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
160 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
161 createEndpointRegFromPort(port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
162 registerBaseEndpointAndStoreMapping(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx,
164 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
166 // change L3Context for all EPs with same subnet as router port
167 changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), port.getNetworkId(),
168 new Uuid(port.getDeviceId()), neutron, true);
169 // set L3Context as parent for bridge domain which is parent of subnet
170 TenantId tenantId = new TenantId(port.getTenantId().getValue());
171 Optional<Subnet> potentialRouterPortSubnet =
172 SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), neutron.getSubnets());
173 if (!potentialRouterPortSubnet.isPresent()) {
174 LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", port);
177 Subnet routerPortSubnet = potentialRouterPortSubnet.get();
178 ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
179 ForwardingContext l2Bd = new ForwardingContextBuilder().setContextId(l2BdId)
180 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
181 .setParent(MappingUtils.createParent(routerL3Context, MappingUtils.L3_CONTEXT))
183 rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd,
185 // set virtual router IP for subnet
186 NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(routerPortSubnet, neutron, null);
187 rwTx.merge(LogicalDatastoreType.CONFIGURATION,
188 L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
190 // does the same for tenant forwarding domains
191 processTenantForwarding(routerPortSubnet, routerL3Context, portIpWithSubnet, tenantId, rwTx);
193 DataStoreHelper.submitToDs(rwTx);
194 } else if (PortUtils.isDhcpPort(port)) {
195 // process as normal port but put it to DHCP group
196 LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
197 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
198 if (!firstFixedIps.isPresent()) {
199 LOG.warn("DHCP port does not have an IP address. {}", port);
202 FixedIps ipWithSubnet = firstFixedIps.get();
203 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
204 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
205 epgsFromSecGroups.add(NetworkService.EPG_ID);
206 AddressEndpointRegBuilder l2BaseEp =
207 createBasicMacAddrEpInputBuilder(port, networkContainment, Collections.emptyList());
208 AddressEndpointRegBuilder l3BaseEp =
209 createBasicL3AddrEpInputBuilder(port, networkContainment, epgsFromSecGroups, neutron);
211 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
212 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
213 createEndpointRegFromPort(port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
214 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
215 registerBaseEndpointAndStoreMapping(ImmutableList.of(l3BaseEp.build(), l2BaseEp.build()), port, rwTx,
217 registerMetadataServiceForDhcpPort(port, neutron, l2BaseEp, rwTx, true);
218 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
219 DataStoreHelper.submitToDs(rwTx);
220 } else if (PortUtils.isNormalPort(port)) {
221 LOG.trace("Port is normal port: {}", port.getUuid().getValue());
222 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
224 AddressEndpointRegBuilder l2BaseEp;
225 AddressEndpointRegBuilder l3BaseEp = null;
226 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
227 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
228 epgsFromSecGroups.add(NetworkClient.EPG_ID);
229 if (firstFixedIps.isPresent()) {
230 // endpoint has only one network containment therefore only first IP is used
231 FixedIps ipWithSubnet = firstFixedIps.get();
232 NetworkDomainId containment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
233 epInBuilder = createEndpointRegFromPort(port, ipWithSubnet, containment, epgsFromSecGroups, neutron);
234 l2BaseEp = createBasicMacAddrEpInputBuilder(port, containment, epgsFromSecGroups);
235 l3BaseEp = createBasicL3AddrEpInputBuilder(port, containment, epgsFromSecGroups, neutron);
236 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
238 NetworkDomainId containment = new NetworkDomainId(port.getNetworkId().getValue());
239 epInBuilder = createEndpointRegFromPort(port, null, containment, epgsFromSecGroups, neutron);
240 l2BaseEp = createBasicMacAddrEpInputBuilder(port, containment, epgsFromSecGroups);
242 List<AddressEndpointReg> baseEpRegs = new ArrayList<>();
243 baseEpRegs.add(l2BaseEp.build());
244 if (l3BaseEp != null) {
245 baseEpRegs.add(l3BaseEp.build());
247 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
248 registerBaseEndpointAndStoreMapping(baseEpRegs, port, rwTx, addBaseEpMapping);
249 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
250 DataStoreHelper.submitToDs(rwTx);
251 } else if (PortUtils.isRouterGatewayPort(port)) {
252 // do nothing because actual trigger is attaching of port to router
253 LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
254 } else if (PortUtils.isFloatingIpPort(port)) {
255 // do nothing because trigger is floating IP
256 LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
258 LOG.warn("Unknown port: {}", port);
262 private Port cloneMetadataPortFromDhcpPort(Port port, IpPrefix metadataPrefix) {
263 IpAddress metadataIp = MappingUtils.ipPrefixToIpAddress(metadataPrefix);
264 List<FixedIps> metadataIps = port.getFixedIps().stream().map(fi -> {
265 FixedIpsKey key = new FixedIpsKey(metadataIp, fi.getKey().getSubnetId());
266 return new FixedIpsBuilder(fi).setKey(key).setIpAddress(metadataIp).build();
267 }).collect(Collectors.toList());
268 return new PortBuilder(port).setFixedIps(metadataIps).build();
271 private void registerMetadataServiceForDhcpPort(Port port, Neutron neutron, AddressEndpointRegBuilder childEpToAdd,
272 ReadWriteTransaction rwTx, boolean registerMapping) {
273 Optional<NetworkDomainId> resolveNetworkContainment = PortUtils.resolveNetworkContainment(port);
274 if (!resolveNetworkContainment.isPresent()) {
275 LOG.warn("DHCP port does not have an IP address. {}", port);
278 AddressEndpointRegBuilder metadataEp =
279 createBasicL3AddrEpInputBuilder(cloneMetadataPortFromDhcpPort(port, metadataIpPrefix),
280 resolveNetworkContainment.get(), Lists.newArrayList(MetadataService.EPG_ID), neutron);
281 AddressEndpointKey aek = new AddressEndpointKey(metadataEp.getAddress(), metadataEp.getAddressType(),
282 metadataEp.getContextId(), metadataEp.getContextType());
283 Optional<AddressEndpoint> optMetadataEp =
284 DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek), rwTx);
285 if (!optMetadataEp.isPresent()) {
286 setParentChildRelationshipForEndpoints(metadataEp, childEpToAdd);
288 List<ChildEndpoint> childs = optMetadataEp.get().getChildEndpoint();
289 childs.add(createChildEndpoint(childEpToAdd));
290 metadataEp.setChildEndpoint(childs);
292 registerBaseEndpointAndStoreMapping(ImmutableList.of(metadataEp.build()), port, rwTx, registerMapping);
295 private void setParentChildRelationshipForEndpoints(AddressEndpointRegBuilder parentEp,
296 AddressEndpointRegBuilder childEp) {
297 childEp.setParentEndpointChoice(new ParentEndpointCaseBuilder()
298 .setParentEndpoint(ImmutableList.<ParentEndpoint>of(createParentEndpoint(parentEp))).build());
299 parentEp.setChildEndpoint(ImmutableList.<ChildEndpoint>of(createChildEndpoint(childEp)));
303 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
304 // this will be removed when deprecated classes will be cleared.
305 private void processTenantForwarding(Subnet routerPortSubnet, ContextId routerL3Context, FixedIps portIpWithSubnet,
306 TenantId tenantId, ReadWriteTransaction rwTx) {
307 L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
308 L2BridgeDomain l2Bd =
309 new L2BridgeDomainBuilder().setId(l2BdId).setParent(new L3ContextId(routerL3Context)).build();
310 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
311 // set virtual router IP for subnet
312 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnet =
313 NeutronSubnetAware.createTenantSubnet(routerPortSubnet, portIpWithSubnet.getIpAddress());
314 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet);
318 * Registers endpoint from {@link Port} and method parameters.
319 * Always creates registration input for L2 endpoint.
320 * Creates registration input for L3 endpoint if fixedIps argument is not null.
323 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
324 // this will be removed when deprecated classes will be cleared.
325 private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createEndpointRegFromPort(
326 Port port, FixedIps fixedIps, NetworkDomainId networkContainment, List<EndpointGroupId> endpointGroupIds,
328 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
329 createBasicEndpointInputBuilder(port).setNetworkContainment(networkContainment);
330 if (fixedIps != null) {
331 L3Address l3Address = resolveL3AddressFromPort(port, fixedIps, neutron);
332 epInBuilder.setL3Address(ImmutableList.of(l3Address));
334 epInBuilder.setEndpointGroups(endpointGroupIds);
338 private void changeL3ContextForEpsInSubnet(Uuid subnetUuid, Uuid networkId, Uuid routerId, Neutron neutron,
339 boolean routerInterfAdded) {
340 if (neutron == null) {
341 LOG.debug("No new data are written, there is no L3 context in subnet {} to update", subnetUuid);
344 java.util.Optional<Subnet> optSubnet = neutron.getSubnets()
347 .filter(subnet -> subnet.getNetworkId() != null
348 && subnet.getUuid().getValue().equals(subnetUuid.getValue()))
350 if (!optSubnet.isPresent()) {
351 LOG.error("Failed to update metadata endpoint in subnet {}. Could not resolve Network ID", subnetUuid);
353 AddressEndpointUnregBuilder metadataEpUnreg =
354 new AddressEndpointUnregBuilder().setAddress(String.valueOf(metadataIpPrefix.getValue()))
355 .setAddressType(IpPrefixType.class)
356 .setContextType(MappingUtils.L3_CONTEXT);
357 if (routerInterfAdded) {
358 metadataEpUnreg.setContextId(new ContextId(networkId.getValue()));
360 metadataEpUnreg.setContextId(new ContextId(routerId.getValue()));
362 epRegistrator.unregisterEndpoint(metadataEpUnreg.build());
364 Set<Port> portsInSameSubnet = PortUtils.findPortsBySubnet(subnetUuid, neutron.getPorts());
365 for (Port portInSameSubnet : portsInSameSubnet) {
366 if (PortUtils.isNormalPort(portInSameSubnet) || PortUtils.isDhcpPort(portInSameSubnet)
367 || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
368 // endpoints are created only from neutron normal port or DHCP port
369 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(portInSameSubnet);
370 if (firstFixedIps.isPresent()) {
371 // endpoint has only one network containment therefore only first IP is used
372 FixedIps ipWithSubnet = firstFixedIps.get();
373 List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
374 if (PortUtils.isDhcpPort(portInSameSubnet)
375 || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
376 endpointGroupIds.add(NetworkService.EPG_ID);
377 } else if (PortUtils.isNormalPort(portInSameSubnet)) {
378 endpointGroupIds.add(NetworkClient.EPG_ID);
380 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
381 AddressEndpointRegBuilder l2BaseEp =
382 createBasicMacAddrEpInputBuilder(portInSameSubnet, networkContainment, endpointGroupIds);
383 AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(portInSameSubnet,
384 networkContainment, endpointGroupIds, neutron);
386 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
387 AddressEndpointUnregBuilder addrEpUnreg =
388 new AddressEndpointUnregBuilder().setAddress(l3BaseEp.getAddress())
389 .setAddressType(l3BaseEp.getAddressType())
390 .setContextType(l3BaseEp.getContextType());
391 if (routerInterfAdded) {
392 addrEpUnreg.setContextId(new ContextId(networkId.getValue()));
394 addrEpUnreg.setContextId(new ContextId(routerId.getValue()));
396 epRegistrator.unregisterEndpoint(addrEpUnreg.build());
397 if (routerInterfAdded) {
398 l3BaseEp.setContextId(new ContextId(routerId.getValue()));
400 l3BaseEp.setContextId(new ContextId(networkId.getValue()));
402 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
403 RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder()
404 .setAddressEndpointReg(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build())).build();
405 epRegistrator.registerEndpoint(regBaseEpInput);
406 if (PortUtils.isDhcpPort(portInSameSubnet)) {
407 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
408 registerMetadataServiceForDhcpPort(portInSameSubnet, neutron, l2BaseEp, rwTx, false);
409 DataStoreHelper.submitToDs(rwTx);
411 modifyL3ContextForEndpoints(portInSameSubnet, ipWithSubnet, l3BaseEp.getContextId());
417 private ChildEndpoint createChildEndpoint(AddressEndpointRegBuilder builder) {
418 return new ChildEndpointBuilder().setAddress(builder.getAddress())
419 .setAddressType(builder.getAddressType())
420 .setContextId(builder.getContextId())
421 .setContextType(builder.getContextType())
425 private ParentEndpoint createParentEndpoint(AddressEndpointRegBuilder builder) {
426 return new ParentEndpointBuilder().setAddress(builder.getAddress())
427 .setAddressType(builder.getAddressType())
428 .setContextId(builder.getContextId())
429 .setContextType(builder.getContextType())
434 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
435 // this will be removed when deprecated classes will be cleared.
436 private void modifyL3ContextForEndpoints(Port port, FixedIps resolvedPortFixedIp, ContextId newContextId) {
437 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
438 createBasicEndpointInputBuilder(port);
439 epInBuilder.setNetworkContainment(new NetworkDomainId(resolvedPortFixedIp.getSubnetId().getValue()));
440 L3Address l3Address = new L3AddressBuilder().setL3Context(new L3ContextId(newContextId))
441 .setIpAddress(resolvedPortFixedIp.getIpAddress())
443 epInBuilder.setL3Address(ImmutableList.of(l3Address));
444 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
445 epgsFromSecGroups.add(NetworkClient.EPG_ID);
446 epInBuilder.setEndpointGroups(epgsFromSecGroups);
447 epRegistrator.registerEndpoint(epInBuilder.build());
449 L3ContextId oldL3Context = new L3ContextId(port.getNetworkId().getValue());
450 L3 l3 = new L3Builder().setL3Context(oldL3Context).setIpAddress(resolvedPortFixedIp.getIpAddress()).build();
451 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput epUnreg =
452 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder()
453 .setL3(ImmutableList.of(l3)).build();
454 epRegistrator.unregisterEndpoint(epUnreg);
457 private AddressEndpointRegBuilder createBasicMacAddrEpInputBuilder(Port port, NetworkDomainId networkContainment,
458 @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
459 AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
460 .setAddress(port.getMacAddress().getValue())
461 .setAddressType(MacAddressType.class)
462 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
463 .setContextId(new ContextId(port.getNetworkId().getValue()))
464 .setTenant(new TenantId(port.getTenantId().getValue()))
465 .setTimestamp(System.currentTimeMillis());
466 List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
467 addrEpbuilder.setEndpointGroup(epgs);
468 if (networkContainment != null) {
469 addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder()
470 .setContainment(new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
471 .setNetworkDomainType(MappingUtils.SUBNET)
475 return addrEpbuilder;
478 private AddressEndpointRegBuilder createBasicL3AddrEpInputBuilder(Port port, NetworkDomainId networkContainment,
479 @Nullable List<EndpointGroupId> endpointGroupsToAdd, Neutron neutron) {
480 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
481 if (!firstFixedIps.isPresent()) {
482 throw new IllegalStateException(
483 "Failed to resolve FixedIps for port " + port.getKey() + ". Cannot register L3 Address endpoint.");
485 ContextId resolveL3ContextForPort = resolveL3ContextForPort(port, port.getFixedIps().get(0), neutron);
487 AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
488 .setAddress(MappingUtils.ipAddressToStringIpPrefix(firstFixedIps.get().getIpAddress()))
489 .setAddressType(IpPrefixType.class)
490 .setContextType(MappingUtils.L3_CONTEXT)
491 .setContextId(resolveL3ContextForPort)
492 .setTenant(new TenantId(port.getTenantId().getValue()))
493 .setTimestamp(System.currentTimeMillis());
494 List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
495 addrEpbuilder.setEndpointGroup(epgs);
496 if (networkContainment != null) {
497 addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder()
498 .setContainment(new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
499 .setNetworkDomainType(MappingUtils.SUBNET)
503 return addrEpbuilder;
506 private List<EndpointGroupId> concatEndpointGroups(List<Uuid> securityGroups,
507 @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
508 List<EndpointGroupId> epgs = new ArrayList<>();
509 if (securityGroups != null) {
510 for (Uuid sgId : securityGroups) {
511 epgs.add(new EndpointGroupId(sgId.getValue()));
514 if (endpointGroupsToAdd != null) {
515 epgs.addAll(endpointGroupsToAdd);
521 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
522 // this will be removed when deprecated classes will be cleared.
523 private static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createBasicEndpointInputBuilder(
525 return new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder()
526 .setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue()))
527 .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
528 .setTenant(new TenantId(port.getTenantId().getValue()))
529 .setTimestamp(System.currentTimeMillis());
532 private static List<EndpointGroupId> resolveEpgIdsFromSecGroups(@Nullable List<Uuid> securityGroups) {
533 List<EndpointGroupId> epgIds = new ArrayList<>();
534 if ((securityGroups == null || securityGroups.isEmpty())) {
537 for (Uuid secGrp : securityGroups) {
538 epgIds.add(new EndpointGroupId(secGrp.getValue()));
544 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
545 // this will be removed when deprecated classes will be cleared.
546 private void registerEndpointAndStoreMapping(
547 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput regEpInput,
548 Port port, ReadWriteTransaction rwTx) {
549 boolean isRegisteredEndpoint = epRegistrator.registerEndpoint(regEpInput);
550 if (!isRegisteredEndpoint) {
551 LOG.error("Failed to register endpoint: {}", regEpInput);
554 UniqueId portId = new UniqueId(port.getUuid().getValue());
555 EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()),
556 new MacAddress(port.getMacAddress().getValue()));
557 LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}",
558 port.getUuid().getValue(), port.getDeviceOwner(), epKey);
559 EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
560 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort,
562 PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
563 rwTx.put(LogicalDatastoreType.OPERATIONAL,
564 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint,
569 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
570 // this will be removed when deprecated classes will be cleared.
571 private void unregisterEndpointAndRemoveMapping(
572 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput unregEpInput,
573 Port port, ReadWriteTransaction rwTx) {
574 boolean isUnregisteredEndpoint = epRegistrator.unregisterEndpoint(unregEpInput);
575 if (isUnregisteredEndpoint) {
576 UniqueId portId = new UniqueId(port.getUuid().getValue());
577 EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()),
578 new MacAddress(port.getMacAddress().getValue()));
579 LOG.trace("Removing Port-Endpoint mapping for port {} (device owner {}) and endpoint {}",
580 port.getUuid().getValue(), port.getDeviceOwner(), epKey);
581 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
582 NeutronGbpIidFactory.endpointByPortIid(portId), rwTx);
583 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
584 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
588 private void unregisterEndpointAndRemoveMapping(UnregisterEndpointInput baseEpUnreg, Port port,
589 ReadWriteTransaction rwTx, boolean removeBaseEpMappings) {
590 boolean isUnregisteredBaseEndpoint = epRegistrator.unregisterEndpoint(baseEpUnreg);
591 if (isUnregisteredBaseEndpoint) {
592 UniqueId portId = new UniqueId(port.getUuid().getValue());
593 PortByBaseEndpointKey portByBaseEndpointKey = new PortByBaseEndpointKey(port.getMacAddress().getValue(),
594 MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
595 LOG.trace("Removing Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
596 port.getUuid().getValue(), port.getDeviceOwner(), portByBaseEndpointKey);
597 if (removeBaseEpMappings) {
598 removeBaseEndpointMappings(portByBaseEndpointKey, portId, rwTx);
603 private void registerBaseEndpointAndStoreMapping(List<AddressEndpointReg> addrEpRegs, Port port,
604 WriteTransaction writeTx, boolean addBaseEpMappings) {
605 RegisterEndpointInput regBaseEpInput =
606 new RegisterEndpointInputBuilder().setAddressEndpointReg(addrEpRegs).build();
608 boolean isRegisteredBaseEndpoint = epRegistrator.registerEndpoint(regBaseEpInput);
609 if (!isRegisteredBaseEndpoint) {
610 LOG.error("Failed to register address endpoint: {}", addrEpRegs);
613 for (AddressEndpointReg addrEpReg : addrEpRegs) {
614 if (MappingUtils.L2_BRDIGE_DOMAIN.equals(addrEpReg.getContextType()) && addBaseEpMappings) {
615 UniqueId portId = new UniqueId(port.getUuid().getValue());
616 LOG.trace("Adding Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
618 AddressEndpointKey addrEpKey = new AddressEndpointKey(addrEpReg.getAddress(),
619 addrEpReg.getAddressType(), addrEpReg.getContextId(), addrEpReg.getContextType());
620 addBaseEndpointMappings(addrEpKey, portId, writeTx);
625 private void addBaseEndpointMappings(AddressEndpointKey addrEpKey, UniqueId portId, WriteTransaction writeTx) {
626 BaseEndpointByPort baseEndpointByPort = MappingFactory.createBaseEndpointByPort(addrEpKey, portId);
627 writeTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.baseEndpointByPortIid(portId),
628 baseEndpointByPort, true);
629 PortByBaseEndpoint portByBaseEndpoint = MappingFactory.createPortByBaseEndpoint(portId, addrEpKey);
630 writeTx.put(LogicalDatastoreType.OPERATIONAL,
631 NeutronGbpIidFactory.portByBaseEndpointIid(new PortByBaseEndpointKey(portByBaseEndpoint.getKey())),
632 portByBaseEndpoint, true);
635 private void removeBaseEndpointMappings(PortByBaseEndpointKey portByBaseEndpointKey, UniqueId portId,
636 ReadWriteTransaction rwTx) {
637 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
638 NeutronGbpIidFactory.baseEndpointByPortIid(portId), rwTx);
639 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
640 NeutronGbpIidFactory.portByBaseEndpointIid(portByBaseEndpointKey), rwTx);
644 public void onUpdated(Port oldPort, Port newPort, Neutron oldNeutron, Neutron newNeutron) {
645 LOG.trace("updated port - OLD: {}\nNEW: {}", oldPort, newPort);
646 onDeleted(oldPort, oldNeutron, newNeutron, false);
647 onCreated(newPort, newNeutron, false);
651 public void onDeleted(Port deletedItem, Neutron oldNeutron, Neutron newNeutron) {
652 onDeleted(deletedItem, oldNeutron, newNeutron, true);
655 public void onDeleted(Port port, Neutron oldNeutron, Neutron newNeutron, boolean removeBaseEpMapping) {
656 LOG.trace("deleted port - {}", port);
657 if (PortUtils.isRouterInterfacePort(port)) {
658 LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
659 // router interface port can have only one IP
660 Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
661 if (!potentialPortIpWithSubnet.isPresent()) {
662 LOG.warn("Illegal state - router interface port does not contain fixed IPs {}", port);
665 FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
666 L3ContextId l3Context = new L3ContextId(port.getNetworkId().getValue());
667 // change L3Context for all new EPs with same subnet as router port
668 changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), port.getNetworkId(),
669 new Uuid(port.getDeviceId()), newNeutron, false);
670 // set L3Context as parent for bridge domain which is parent of subnet
671 TenantId tenantId = new TenantId(port.getTenantId().getValue());
672 Optional<Subnet> potentialRouterPortSubnet =
673 SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), oldNeutron.getSubnets());
674 if (!potentialRouterPortSubnet.isPresent()) {
675 LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", port);
678 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
679 Subnet routerPortSubnet = potentialRouterPortSubnet.get();
680 modifyForwardingOnDelete(routerPortSubnet, l3Context, tenantId, rwTx);
681 ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
682 ForwardingContext fwdCtx = new ForwardingContextBuilder().setContextId(l2BdId)
683 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
684 .setParent(MappingUtils.createParent(l3Context, MappingUtils.L3_CONTEXT))
686 rwTx.merge(LogicalDatastoreType.CONFIGURATION,
687 L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
688 NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron, null);
689 rwTx.put(LogicalDatastoreType.CONFIGURATION,
690 L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()), subnet);
691 unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
692 unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx,
693 removeBaseEpMapping);
694 DataStoreHelper.submitToDs(rwTx);
695 } else if (PortUtils.isDhcpPort(port)) {
696 LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
697 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
698 unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
699 unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx,
700 removeBaseEpMapping);
701 DataStoreHelper.submitToDs(rwTx);
702 if (!oldNeutron.getPorts()
705 .filter(PortUtils::isDhcpPort)
706 .anyMatch(p -> !p.getUuid().equals(port.getUuid()))) {
707 Port metadataPort = cloneMetadataPortFromDhcpPort(port, metadataIpPrefix);
708 if (PortUtils.resolveFirstFixedIps(metadataPort).isPresent()) {
709 ContextId metadataCtx = resolveL3ContextForPort(metadataPort,
710 PortUtils.resolveFirstFixedIps(metadataPort).get(), oldNeutron);
711 AddressEndpointUnregBuilder metadataEpUnreg =
712 new AddressEndpointUnregBuilder().setAddress(String.valueOf(metadataIpPrefix.getValue()))
713 .setAddressType(IpPrefixType.class)
714 .setContextType(MappingUtils.L3_CONTEXT)
715 .setContextId(metadataCtx);
716 epRegistrator.unregisterEndpoint(metadataEpUnreg.build());
719 } else if (PortUtils.isNormalPort(port)) {
720 LOG.trace("Port is normal port: {}", port.getUuid().getValue());
721 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
722 unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
723 unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx,
724 removeBaseEpMapping);
725 DataStoreHelper.submitToDs(rwTx);
726 } else if (PortUtils.isRouterGatewayPort(port)) {
727 // do nothing because actual trigger is detaching of port from router
728 LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
729 } else if (PortUtils.isFloatingIpPort(port)) {
730 // do nothing because trigger is floating IP
731 LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
733 LOG.warn("Unknown port: {}", port);
738 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
739 // this will be removed when deprecated classes will be cleared.
740 private void modifyForwardingOnDelete(Subnet routerPortSubnet, L3ContextId l3contextId, TenantId tenantId,
741 ReadWriteTransaction rwTx) {
742 L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
743 L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(l3contextId).build();
744 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd);
745 // remove virtual router IP for subnet
746 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet tenantSubnet =
747 NeutronSubnetAware.createTenantSubnet(routerPortSubnet, null);
748 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, tenantSubnet.getId()),
752 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
753 // this will be removed when deprecated classes will be cleared.
754 private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput createUnregisterBaseEndpointInput(
755 Port port, Neutron neutron) {
756 List<AddressEndpointUnreg> list = new ArrayList<>();
757 AddressEndpointUnregBuilder addrL2EpUnregBuilder = new AddressEndpointUnregBuilder();
758 addrL2EpUnregBuilder.setAddress(port.getMacAddress().getValue())
759 .setAddressType(MacAddressType.class)
760 .setContextId(new ContextId(port.getNetworkId().getValue()))
761 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN);
762 list.add(addrL2EpUnregBuilder.build());
763 Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
764 if (potentialFirstIp.isPresent()) {
765 ContextId l3ContextId = resolveL3ContextForPort(port, potentialFirstIp.get(), neutron);
766 AddressEndpointUnregBuilder addrL3EpUnregBuilder = new AddressEndpointUnregBuilder();
768 .setAddress(MappingUtils.ipAddressToStringIpPrefix(potentialFirstIp.get().getIpAddress()))
769 .setAddressType(IpPrefixType.class)
770 .setContextId(l3ContextId)
771 .setContextType(L3Context.class);
772 list.add(addrL3EpUnregBuilder.build());
774 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
775 inputBuilder.setAddressEndpointUnreg(list);
776 return inputBuilder.build();
780 @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
781 // this will be removed when deprecated classes will be cleared.
782 private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput createUnregisterEndpointInput(
783 Port port, Neutron neutron) {
784 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder inputBuilder =
785 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder();
786 L2 l2Ep = new L2Builder().setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue()))
787 .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
789 inputBuilder.setL2(ImmutableList.of(l2Ep));
790 // we've registered EP with only first IP so remove only EP with first IP
791 Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
792 if (potentialFirstIp.isPresent()) {
793 FixedIps firstIp = potentialFirstIp.get();
794 L3Address l3Address = resolveL3AddressFromPort(port, firstIp, neutron);
795 L3 l3 = new L3Builder().setIpAddress(l3Address.getIpAddress())
796 .setL3Context(l3Address.getL3Context())
798 inputBuilder.setL3(ImmutableList.of(l3));
800 return inputBuilder.build();
804 private static L3Address resolveL3AddressFromPort(Port port, FixedIps portFixedIPs, Neutron neutron) {
805 Set<Port> routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts());
806 for (Port routerIfacePort : routerIfacePorts) {
807 Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId();
808 // if port is in the same subnet as router interface then we want to use L3Context of
810 if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) {
811 L3ContextId epL3ContextId = new L3ContextId(routerIfacePort.getDeviceId());
812 LOG.trace("Router interface port was found in the same subnet as port have {}", port);
813 return new L3AddressBuilder().setL3Context(epL3ContextId)
814 .setIpAddress(portFixedIPs.getIpAddress())
818 return new L3AddressBuilder().setL3Context(new L3ContextId(port.getNetworkId().getValue()))
819 .setIpAddress(portFixedIPs.getIpAddress())
823 private static ContextId resolveL3ContextForPort(Port port, FixedIps portFixedIPs, Neutron neutron) {
824 Set<Port> routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts());
825 for (Port routerIfacePort : routerIfacePorts) {
826 Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId();
827 // if port is in the same subnet as router interface then we want to use L3Context of
829 if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) {
830 LOG.trace("Router interface port was found in the same subnet as port have {}", port);
831 return new ContextId(routerIfacePort.getDeviceId());
834 return new ContextId(port.getNetworkId().getValue());