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.Collections;
14 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import java.util.stream.Collectors;
19 import javax.annotation.Nullable;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
26 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.MetadataService;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
31 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
32 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
33 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils;
34 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
35 import org.opendaylight.groupbasedpolicy.util.IidFactory;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpoint;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpointKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
93 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
97 import com.google.common.base.Optional;
98 import com.google.common.collect.ImmutableList;
99 import com.google.common.collect.Lists;
101 public class NeutronPortAware implements NeutronAware<Port> {
103 private static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
104 public static final InstanceIdentifier<Port> PORT_WILDCARD_IID =
105 InstanceIdentifier.builder(Neutron.class).child(Ports.class).child(Port.class).build();
106 private final DataBroker dataProvider;
107 private final EndpointRegistrator epRegistrator;
108 private final IpPrefix metadataIpPrefix;
110 public NeutronPortAware(DataBroker dataProvider, EndpointRegistrator epRegistrator,
111 @Nullable IpPrefix metadataIpPrefix) {
112 this.dataProvider = checkNotNull(dataProvider);
113 this.epRegistrator = checkNotNull(epRegistrator);
114 this.metadataIpPrefix = checkNotNull(metadataIpPrefix);
118 public void onCreated(Port createdItem, Neutron neutron) {
119 onCreated(createdItem, neutron, true);
122 public void onCreated(Port port, Neutron neutron, boolean addBaseEpMapping) {
123 LOG.trace("created port - {}", port);
124 if (PortUtils.isRouterInterfacePort(port)) {
125 LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
126 // router interface port can have only one IP
127 Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
128 if (!potentialPortIpWithSubnet.isPresent()) {
129 LOG.warn("Illegal state - router interface port does not contain fixed IPs {}", port);
132 FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
133 ContextId routerL3Context = new ContextId(port.getDeviceId());
134 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
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 addBaseEndpointMappings(addrEpKey, portId, rwTx);
139 // Add Qrouter and VPProuter port as Endpoint
140 if (port.getAugmentation(PortBindingExtension.class) != null && PortUtils.DEVICE_VIF_TYPE
141 .equals(port.getAugmentation(PortBindingExtension.class).getVifType())) {
142 LOG.trace("Port is QRouter port: {}", port.getUuid().getValue());
143 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
144 if (!firstFixedIps.isPresent()) {
145 LOG.warn("QRouter port does not have an IP address. {}", port);
148 FixedIps ipWithSubnet = firstFixedIps.get();
149 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
150 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
151 epgsFromSecGroups.add(NetworkService.EPG_ID);
152 // BUILD BASE ENDPOINT
153 AddressEndpointRegBuilder l2BaseEp =
154 createBasicMacAddrEpInputBuilder(port, networkContainment, epgsFromSecGroups);
155 AddressEndpointRegBuilder l3BaseEp =
156 createBasicL3AddrEpInputBuilder(port, networkContainment, epgsFromSecGroups, neutron);
157 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
159 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
160 createEndpointRegFromPort(port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
161 registerBaseEndpointAndStoreMapping(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx,
163 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
165 // change L3Context for all EPs with same subnet as router port
166 changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), port.getNetworkId(),
167 new Uuid(port.getDeviceId()), neutron, true);
168 // set L3Context as parent for bridge domain which is parent of subnet
169 TenantId tenantId = new TenantId(port.getTenantId().getValue());
170 Optional<Subnet> potentialRouterPortSubnet =
171 SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), neutron.getSubnets());
172 if (!potentialRouterPortSubnet.isPresent()) {
173 LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", port);
176 Subnet routerPortSubnet = potentialRouterPortSubnet.get();
177 ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
178 ForwardingContext l2Bd = new ForwardingContextBuilder().setContextId(l2BdId)
179 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
180 .setParent(MappingUtils.createParent(routerL3Context, MappingUtils.L3_CONTEXT))
182 rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd,
184 // set virtual router IP for subnet
185 NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(routerPortSubnet, neutron, null);
186 rwTx.merge(LogicalDatastoreType.CONFIGURATION,
187 L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
189 // does the same for tenant forwarding domains
190 processTenantForwarding(routerPortSubnet, routerL3Context, portIpWithSubnet, tenantId, rwTx);
192 DataStoreHelper.submitToDs(rwTx);
193 } else if (PortUtils.isDhcpPort(port)) {
194 // process as normal port but put it to DHCP group
195 LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
196 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
197 if (!firstFixedIps.isPresent()) {
198 LOG.warn("DHCP port does not have an IP address. {}", port);
201 FixedIps ipWithSubnet = firstFixedIps.get();
202 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
203 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
204 epgsFromSecGroups.add(NetworkService.EPG_ID);
205 AddressEndpointRegBuilder l2BaseEp =
206 createBasicMacAddrEpInputBuilder(port, networkContainment, Collections.emptyList());
207 AddressEndpointRegBuilder l3BaseEp =
208 createBasicL3AddrEpInputBuilder(port, networkContainment, epgsFromSecGroups, neutron);
210 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
211 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
212 createEndpointRegFromPort(port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
213 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
214 registerBaseEndpointAndStoreMapping(ImmutableList.of(l3BaseEp.build(), l2BaseEp.build()), port, rwTx,
216 registerMetadataServiceForDhcpPort(port, neutron, l2BaseEp, rwTx, true);
217 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
218 DataStoreHelper.submitToDs(rwTx);
219 } else if (PortUtils.isNormalPort(port)) {
220 LOG.trace("Port is normal port: {}", port.getUuid().getValue());
221 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
223 AddressEndpointRegBuilder l2BaseEp;
224 AddressEndpointRegBuilder l3BaseEp = null;
225 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
226 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
227 epgsFromSecGroups.add(NetworkClient.EPG_ID);
228 if (firstFixedIps.isPresent()) {
229 // endpoint has only one network containment therefore only first IP is used
230 FixedIps ipWithSubnet = firstFixedIps.get();
231 NetworkDomainId containment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
232 epInBuilder = createEndpointRegFromPort(port, ipWithSubnet, containment, epgsFromSecGroups, neutron);
233 l2BaseEp = createBasicMacAddrEpInputBuilder(port, containment, epgsFromSecGroups);
234 l3BaseEp = createBasicL3AddrEpInputBuilder(port, containment, epgsFromSecGroups, neutron);
235 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
237 NetworkDomainId containment = new NetworkDomainId(port.getNetworkId().getValue());
238 epInBuilder = createEndpointRegFromPort(port, null, containment, epgsFromSecGroups, neutron);
239 l2BaseEp = createBasicMacAddrEpInputBuilder(port, containment, epgsFromSecGroups);
241 List<AddressEndpointReg> baseEpRegs = new ArrayList<>();
242 baseEpRegs.add(l2BaseEp.build());
243 if (l3BaseEp != null) {
244 baseEpRegs.add(l3BaseEp.build());
246 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
247 registerBaseEndpointAndStoreMapping(baseEpRegs, port, rwTx, addBaseEpMapping);
248 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
249 DataStoreHelper.submitToDs(rwTx);
250 } else if (PortUtils.isRouterGatewayPort(port)) {
251 // do nothing because actual trigger is attaching of port to router
252 LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
253 } else if (PortUtils.isFloatingIpPort(port)) {
254 // do nothing because trigger is floating IP
255 LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
257 LOG.warn("Unknown port: {}", port);
261 private Port cloneMetadataPortFromDhcpPort(Port port, IpPrefix metadataPrefix) {
262 IpAddress metadataIp = MappingUtils.ipPrefixToIpAddress(metadataPrefix);
263 List<FixedIps> metadataIps = port.getFixedIps().stream().map(fi -> {
264 FixedIpsKey key = new FixedIpsKey(metadataIp, fi.getKey().getSubnetId());
265 return new FixedIpsBuilder(fi).setKey(key).setIpAddress(metadataIp).build();
266 }).collect(Collectors.toList());
267 return new PortBuilder(port).setFixedIps(metadataIps).build();
270 private void registerMetadataServiceForDhcpPort(Port port, Neutron neutron, AddressEndpointRegBuilder childEpToAdd,
271 ReadWriteTransaction rwTx, boolean registerMapping) {
272 Optional<NetworkDomainId> resolveNetworkContainment = PortUtils.resolveNetworkContainment(port);
273 if (!resolveNetworkContainment.isPresent()) {
274 LOG.warn("DHCP port does not have an IP address. {}", port);
277 AddressEndpointRegBuilder metadataEp =
278 createBasicL3AddrEpInputBuilder(cloneMetadataPortFromDhcpPort(port, metadataIpPrefix),
279 resolveNetworkContainment.get(), Lists.newArrayList(MetadataService.EPG_ID), neutron);
280 AddressEndpointKey aek = new AddressEndpointKey(metadataEp.getAddress(), metadataEp.getAddressType(),
281 metadataEp.getContextId(), metadataEp.getContextType());
282 Optional<AddressEndpoint> optMetadataEp =
283 DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek), rwTx);
284 if (!optMetadataEp.isPresent()) {
285 setParentChildRelationshipForEndpoints(metadataEp, childEpToAdd);
287 List<ChildEndpoint> childs = optMetadataEp.get().getChildEndpoint();
288 childs.add(createChildEndpoint(childEpToAdd));
289 metadataEp.setChildEndpoint(childs);
291 registerBaseEndpointAndStoreMapping(ImmutableList.of(metadataEp.build()), port, rwTx, registerMapping);
294 private void setParentChildRelationshipForEndpoints(AddressEndpointRegBuilder parentEp,
295 AddressEndpointRegBuilder childEp) {
296 childEp.setParentEndpointChoice(new ParentEndpointCaseBuilder()
297 .setParentEndpoint(ImmutableList.<ParentEndpoint>of(createParentEndpoint(parentEp))).build());
298 parentEp.setChildEndpoint(ImmutableList.<ChildEndpoint>of(createChildEndpoint(childEp)));
302 private void processTenantForwarding(Subnet routerPortSubnet, ContextId routerL3Context, FixedIps portIpWithSubnet,
303 TenantId tenantId, ReadWriteTransaction rwTx) {
304 L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
305 L2BridgeDomain l2Bd =
306 new L2BridgeDomainBuilder().setId(l2BdId).setParent(new L3ContextId(routerL3Context)).build();
307 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
308 // set virtual router IP for subnet
309 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnet =
310 NeutronSubnetAware.createTenantSubnet(routerPortSubnet, portIpWithSubnet.getIpAddress());
311 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet);
315 * Registers endpoint from {@link Port} and method parameters.
316 * Always creates registration input for L2 endpoint.
317 * Creates registration input for L3 endpoint if fixedIps argument is not null.
320 private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createEndpointRegFromPort(
321 Port port, FixedIps fixedIps, NetworkDomainId networkContainment, List<EndpointGroupId> endpointGroupIds,
323 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
324 createBasicEndpointInputBuilder(port).setNetworkContainment(networkContainment);
325 if (fixedIps != null) {
326 L3Address l3Address = resolveL3AddressFromPort(port, fixedIps, neutron);
327 epInBuilder.setL3Address(ImmutableList.of(l3Address));
329 epInBuilder.setEndpointGroups(endpointGroupIds);
333 private void changeL3ContextForEpsInSubnet(Uuid subnetUuid, Uuid networkId, Uuid routerId, Neutron neutron,
334 boolean routerInterfAdded) {
335 if (neutron == null) {
336 LOG.debug("No new data are written, there is no L3 context in subnet {} to update", subnetUuid);
339 java.util.Optional<Subnet> optSubnet = neutron.getSubnets()
342 .filter(subnet -> subnet.getNetworkId() != null
343 && subnet.getUuid().getValue().equals(subnetUuid.getValue()))
345 if (!optSubnet.isPresent()) {
346 LOG.error("Failed to update metadata endpoint in subnet {}. Could not resolve Network ID", subnetUuid);
348 AddressEndpointUnregBuilder metadataEpUnreg =
349 new AddressEndpointUnregBuilder().setAddress(String.valueOf(metadataIpPrefix.getValue()))
350 .setAddressType(IpPrefixType.class)
351 .setContextType(MappingUtils.L3_CONTEXT);
352 if (routerInterfAdded) {
353 metadataEpUnreg.setContextId(new ContextId(networkId.getValue()));
355 metadataEpUnreg.setContextId(new ContextId(routerId.getValue()));
357 epRegistrator.unregisterEndpoint(metadataEpUnreg.build());
359 Set<Port> portsInSameSubnet = PortUtils.findPortsBySubnet(subnetUuid, neutron.getPorts());
360 for (Port portInSameSubnet : portsInSameSubnet) {
361 if (PortUtils.isNormalPort(portInSameSubnet) || PortUtils.isDhcpPort(portInSameSubnet)
362 || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
363 // endpoints are created only from neutron normal port or DHCP port
364 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(portInSameSubnet);
365 if (firstFixedIps.isPresent()) {
366 // endpoint has only one network containment therefore only first IP is used
367 FixedIps ipWithSubnet = firstFixedIps.get();
368 List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
369 if (PortUtils.isDhcpPort(portInSameSubnet)
370 || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
371 endpointGroupIds.add(NetworkService.EPG_ID);
372 } else if (PortUtils.isNormalPort(portInSameSubnet)) {
373 endpointGroupIds.add(NetworkClient.EPG_ID);
375 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
376 AddressEndpointRegBuilder l2BaseEp =
377 createBasicMacAddrEpInputBuilder(portInSameSubnet, networkContainment, endpointGroupIds);
378 AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(portInSameSubnet,
379 networkContainment, endpointGroupIds, neutron);
380 ContextId resolvedCtxId = l3BaseEp.getContextId();
381 ContextId networkCtxId = new ContextId(portInSameSubnet.getNetworkId().getValue());
382 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
383 AddressEndpointUnregBuilder addrEpUnreg =
384 new AddressEndpointUnregBuilder().setAddress(l3BaseEp.getAddress())
385 .setAddressType(l3BaseEp.getAddressType())
386 .setContextType(l3BaseEp.getContextType());
387 if (routerInterfAdded) {
388 addrEpUnreg.setContextId(new ContextId(networkId.getValue()));
390 addrEpUnreg.setContextId(new ContextId(routerId.getValue()));
392 epRegistrator.unregisterEndpoint(addrEpUnreg.build());
393 if (routerInterfAdded) {
394 l3BaseEp.setContextId(new ContextId(routerId.getValue()));
396 l3BaseEp.setContextId(new ContextId(networkId.getValue()));
398 RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder()
399 .setAddressEndpointReg(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build())).build();
400 epRegistrator.registerEndpoint(regBaseEpInput);
401 if (PortUtils.isDhcpPort(portInSameSubnet)) {
402 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
403 registerMetadataServiceForDhcpPort(portInSameSubnet, neutron, l2BaseEp, rwTx, false);
404 DataStoreHelper.submitToDs(rwTx);
406 modifyL3ContextForEndpoints(portInSameSubnet, ipWithSubnet, l3BaseEp.getContextId());
412 private ChildEndpoint createChildEndpoint(AddressEndpointRegBuilder builder) {
413 return new ChildEndpointBuilder().setAddress(builder.getAddress())
414 .setAddressType(builder.getAddressType())
415 .setContextId(builder.getContextId())
416 .setContextType(builder.getContextType())
420 private ParentEndpoint createParentEndpoint(AddressEndpointRegBuilder builder) {
421 return new ParentEndpointBuilder().setAddress(builder.getAddress())
422 .setAddressType(builder.getAddressType())
423 .setContextId(builder.getContextId())
424 .setContextType(builder.getContextType())
429 private void modifyL3ContextForEndpoints(Port port, FixedIps resolvedPortFixedIp, ContextId newContextId) {
430 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder =
431 createBasicEndpointInputBuilder(port);
432 epInBuilder.setNetworkContainment(new NetworkDomainId(resolvedPortFixedIp.getSubnetId().getValue()));
433 L3Address l3Address = new L3AddressBuilder().setL3Context(new L3ContextId(newContextId))
434 .setIpAddress(resolvedPortFixedIp.getIpAddress())
436 epInBuilder.setL3Address(ImmutableList.of(l3Address));
437 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
438 epgsFromSecGroups.add(NetworkClient.EPG_ID);
439 epInBuilder.setEndpointGroups(epgsFromSecGroups);
440 epRegistrator.registerEndpoint(epInBuilder.build());
442 L3ContextId oldL3Context = new L3ContextId(port.getNetworkId().getValue());
443 L3 l3 = new L3Builder().setL3Context(oldL3Context).setIpAddress(resolvedPortFixedIp.getIpAddress()).build();
444 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput epUnreg =
445 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder()
446 .setL3(ImmutableList.of(l3)).build();
447 epRegistrator.unregisterEndpoint(epUnreg);
450 private AddressEndpointRegBuilder createBasicMacAddrEpInputBuilder(Port port, NetworkDomainId networkContainment,
451 @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
452 AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
453 .setAddress(port.getMacAddress().getValue())
454 .setAddressType(MacAddressType.class)
455 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
456 .setContextId(new ContextId(port.getNetworkId().getValue()))
457 .setTenant(new TenantId(port.getTenantId().getValue()))
458 .setTimestamp(System.currentTimeMillis());
459 List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
460 addrEpbuilder.setEndpointGroup(epgs);
461 if (networkContainment != null) {
462 addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder()
463 .setContainment(new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
464 .setNetworkDomainType(MappingUtils.SUBNET)
468 return addrEpbuilder;
471 private AddressEndpointRegBuilder createBasicL3AddrEpInputBuilder(Port port, NetworkDomainId networkContainment,
472 @Nullable List<EndpointGroupId> endpointGroupsToAdd, Neutron neutron) {
473 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
474 if (!firstFixedIps.isPresent()) {
475 throw new IllegalStateException(
476 "Failed to resolve FixedIps for port " + port.getKey() + ". Cannot register L3 Address endpoint.");
478 ContextId resolveL3ContextForPort = resolveL3ContextForPort(port, port.getFixedIps().get(0), neutron);
480 AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
481 .setAddress(MappingUtils.ipAddressToStringIpPrefix(firstFixedIps.get().getIpAddress()))
482 .setAddressType(IpPrefixType.class)
483 .setContextType(MappingUtils.L3_CONTEXT)
484 .setContextId(resolveL3ContextForPort)
485 .setTenant(new TenantId(port.getTenantId().getValue()))
486 .setTimestamp(System.currentTimeMillis());
487 List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
488 addrEpbuilder.setEndpointGroup(epgs);
489 if (networkContainment != null) {
490 addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder()
491 .setContainment(new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
492 .setNetworkDomainType(MappingUtils.SUBNET)
496 return addrEpbuilder;
499 private List<EndpointGroupId> concatEndpointGroups(List<Uuid> securityGroups,
500 @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
501 List<EndpointGroupId> epgs = new ArrayList<>();
502 if (securityGroups != null) {
503 for (Uuid sgId : securityGroups) {
504 epgs.add(new EndpointGroupId(sgId.getValue()));
507 if (endpointGroupsToAdd != null) {
508 epgs.addAll(endpointGroupsToAdd);
514 private static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createBasicEndpointInputBuilder(
516 return new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder()
517 .setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue()))
518 .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
519 .setTenant(new TenantId(port.getTenantId().getValue()))
520 .setTimestamp(System.currentTimeMillis());
523 private static List<EndpointGroupId> resolveEpgIdsFromSecGroups(@Nullable List<Uuid> securityGroups) {
524 List<EndpointGroupId> epgIds = new ArrayList<>();
525 if ((securityGroups == null || securityGroups.isEmpty())) {
528 for (Uuid secGrp : securityGroups) {
529 epgIds.add(new EndpointGroupId(secGrp.getValue()));
535 private void registerEndpointAndStoreMapping(
536 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput regEpInput,
537 Port port, ReadWriteTransaction rwTx) {
538 boolean isRegisteredEndpoint = epRegistrator.registerEndpoint(regEpInput);
539 if (!isRegisteredEndpoint) {
540 LOG.error("Failed to register endpoint: {}", regEpInput);
543 UniqueId portId = new UniqueId(port.getUuid().getValue());
544 EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()),
545 new MacAddress(port.getMacAddress().getValue()));
546 LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}",
547 port.getUuid().getValue(), port.getDeviceOwner(), epKey);
548 EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
549 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort,
551 PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
552 rwTx.put(LogicalDatastoreType.OPERATIONAL,
553 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint,
558 private void unregisterEndpointAndRemoveMapping(
559 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput unregEpInput,
560 Port port, ReadWriteTransaction rwTx) {
561 boolean isUnregisteredEndpoint = epRegistrator.unregisterEndpoint(unregEpInput);
562 if (isUnregisteredEndpoint) {
563 UniqueId portId = new UniqueId(port.getUuid().getValue());
564 EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()),
565 new MacAddress(port.getMacAddress().getValue()));
566 LOG.trace("Removing Port-Endpoint mapping for port {} (device owner {}) and endpoint {}",
567 port.getUuid().getValue(), port.getDeviceOwner(), epKey);
568 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
569 NeutronGbpIidFactory.endpointByPortIid(portId), rwTx);
570 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
571 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
575 private void registerBaseEndpointAndStoreMapping(List<AddressEndpointReg> addrEpRegs, Port port,
576 WriteTransaction wTx, boolean addBaseEpMappings) {
577 RegisterEndpointInput regBaseEpInput =
578 new RegisterEndpointInputBuilder().setAddressEndpointReg(addrEpRegs).build();
580 boolean isRegisteredBaseEndpoint = epRegistrator.registerEndpoint(regBaseEpInput);
581 if (!isRegisteredBaseEndpoint) {
582 LOG.error("Failed to register address endpoint: {}", addrEpRegs);
585 for (AddressEndpointReg addrEpReg : addrEpRegs) {
586 if (MappingUtils.L2_BRDIGE_DOMAIN.equals(addrEpReg.getContextType()) && addBaseEpMappings) {
587 UniqueId portId = new UniqueId(port.getUuid().getValue());
588 LOG.trace("Adding Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
590 AddressEndpointKey addrEpKey = new AddressEndpointKey(addrEpReg.getAddress(),
591 addrEpReg.getAddressType(), addrEpReg.getContextId(), addrEpReg.getContextType());
592 addBaseEndpointMappings(addrEpKey, portId, wTx);
597 private void addBaseEndpointMappings(AddressEndpointKey addrEpKey, UniqueId portId, WriteTransaction wTx) {
598 BaseEndpointByPort baseEndpointByPort = MappingFactory.createBaseEndpointByPort(addrEpKey, portId);
599 wTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.baseEndpointByPortIid(portId),
600 baseEndpointByPort, true);
601 PortByBaseEndpoint portByBaseEndpoint = MappingFactory.createPortByBaseEndpoint(portId, addrEpKey);
602 wTx.put(LogicalDatastoreType.OPERATIONAL,
603 NeutronGbpIidFactory.portByBaseEndpointIid(new PortByBaseEndpointKey(portByBaseEndpoint.getKey())),
604 portByBaseEndpoint, true);
607 private void unregisterEndpointAndRemoveMapping(UnregisterEndpointInput baseEpUnreg, Port port,
608 ReadWriteTransaction rwTx, boolean removeBaseEpMappings) {
609 boolean isUnregisteredBaseEndpoint = epRegistrator.unregisterEndpoint(baseEpUnreg);
610 if (isUnregisteredBaseEndpoint) {
611 UniqueId portId = new UniqueId(port.getUuid().getValue());
612 PortByBaseEndpointKey portByBaseEndpointKey = new PortByBaseEndpointKey(port.getMacAddress().getValue(),
613 MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
614 LOG.trace("Removing Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
615 port.getUuid().getValue(), port.getDeviceOwner(), portByBaseEndpointKey);
616 if (removeBaseEpMappings) {
617 removeBaseEndpointMappings(portByBaseEndpointKey, portId, rwTx);
622 private void removeBaseEndpointMappings(PortByBaseEndpointKey portByBaseEndpointKey, UniqueId portId,
623 ReadWriteTransaction rwTx) {
624 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
625 NeutronGbpIidFactory.baseEndpointByPortIid(portId), rwTx);
626 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
627 NeutronGbpIidFactory.portByBaseEndpointIid(portByBaseEndpointKey), rwTx);
631 public void onUpdated(Port oldPort, Port newPort, Neutron oldNeutron, Neutron newNeutron) {
632 LOG.trace("updated port - OLD: {}\nNEW: {}", oldPort, newPort);
633 onDeleted(oldPort, oldNeutron, newNeutron, false);
634 onCreated(newPort, newNeutron, false);
638 public void onDeleted(Port deletedItem, Neutron oldNeutron, Neutron newNeutron) {
639 onDeleted(deletedItem, oldNeutron, newNeutron, true);
642 public void onDeleted(Port port, Neutron oldNeutron, Neutron newNeutron, boolean removeBaseEpMapping) {
643 LOG.trace("deleted port - {}", port);
644 if (PortUtils.isRouterInterfacePort(port)) {
645 LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
646 // router interface port can have only one IP
647 Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
648 if (!potentialPortIpWithSubnet.isPresent()) {
649 LOG.warn("Illegal state - router interface port does not contain fixed IPs {}", port);
652 FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
653 L3ContextId l3Context = new L3ContextId(port.getNetworkId().getValue());
654 // change L3Context for all new EPs with same subnet as router port
655 changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), port.getNetworkId(),
656 new Uuid(port.getDeviceId()), newNeutron, false);
657 // set L3Context as parent for bridge domain which is parent of subnet
658 TenantId tenantId = new TenantId(port.getTenantId().getValue());
659 Optional<Subnet> potentialRouterPortSubnet =
660 SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), oldNeutron.getSubnets());
661 if (!potentialRouterPortSubnet.isPresent()) {
662 LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", port);
665 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
666 Subnet routerPortSubnet = potentialRouterPortSubnet.get();
667 modifyForwardingOnDelete(routerPortSubnet, l3Context, tenantId, rwTx);
668 ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
669 ForwardingContext fwdCtx = new ForwardingContextBuilder().setContextId(l2BdId)
670 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
671 .setParent(MappingUtils.createParent(l3Context, MappingUtils.L3_CONTEXT))
673 rwTx.merge(LogicalDatastoreType.CONFIGURATION,
674 L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
675 NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron, null);
676 rwTx.put(LogicalDatastoreType.CONFIGURATION,
677 L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()), subnet);
678 unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
679 unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx,
680 removeBaseEpMapping);
681 DataStoreHelper.submitToDs(rwTx);
682 } else if (PortUtils.isDhcpPort(port)) {
683 LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
684 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
685 unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
686 unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx,
687 removeBaseEpMapping);
688 DataStoreHelper.submitToDs(rwTx);
689 if (!oldNeutron.getPorts()
692 .filter(PortUtils::isDhcpPort)
693 .anyMatch(p -> !p.getUuid().equals(port.getUuid()))) {
694 Port metadataPort = cloneMetadataPortFromDhcpPort(port, metadataIpPrefix);
695 if (PortUtils.resolveFirstFixedIps(metadataPort).isPresent()) {
696 ContextId metadataCtx = resolveL3ContextForPort(metadataPort,
697 PortUtils.resolveFirstFixedIps(metadataPort).get(), oldNeutron);
698 AddressEndpointUnregBuilder metadataEpUnreg =
699 new AddressEndpointUnregBuilder().setAddress(String.valueOf(metadataIpPrefix.getValue()))
700 .setAddressType(IpPrefixType.class)
701 .setContextType(MappingUtils.L3_CONTEXT)
702 .setContextId(metadataCtx);
703 epRegistrator.unregisterEndpoint(metadataEpUnreg.build());
706 } else if (PortUtils.isNormalPort(port)) {
707 LOG.trace("Port is normal port: {}", port.getUuid().getValue());
708 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
709 unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
710 unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx,
711 removeBaseEpMapping);
712 DataStoreHelper.submitToDs(rwTx);
713 } else if (PortUtils.isRouterGatewayPort(port)) {
714 // do nothing because actual trigger is detaching of port from router
715 LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
716 } else if (PortUtils.isFloatingIpPort(port)) {
717 // do nothing because trigger is floating IP
718 LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
720 LOG.warn("Unknown port: {}", port);
725 private void modifyForwardingOnDelete(Subnet routerPortSubnet, L3ContextId l3contextId, TenantId tenantId,
726 ReadWriteTransaction rwTx) {
727 L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
728 L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(l3contextId).build();
729 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd);
730 // remove virtual router IP for subnet
731 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet tenantSubnet =
732 NeutronSubnetAware.createTenantSubnet(routerPortSubnet, null);
733 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, tenantSubnet.getId()),
737 private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput createUnregisterBaseEndpointInput(
738 Port port, Neutron neutron) {
739 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
740 List<AddressEndpointUnreg> list = new ArrayList<>();
741 AddressEndpointUnregBuilder addrL2EpUnregBuilder = new AddressEndpointUnregBuilder();
742 addrL2EpUnregBuilder.setAddress(port.getMacAddress().getValue())
743 .setAddressType(MacAddressType.class)
744 .setContextId(new ContextId(port.getNetworkId().getValue()))
745 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN);
746 list.add(addrL2EpUnregBuilder.build());
747 Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
748 if (potentialFirstIp.isPresent()) {
749 ContextId l3ContextId = resolveL3ContextForPort(port, potentialFirstIp.get(), neutron);
750 AddressEndpointUnregBuilder addrL3EpUnregBuilder = new AddressEndpointUnregBuilder();
752 .setAddress(MappingUtils.ipAddressToStringIpPrefix(potentialFirstIp.get().getIpAddress()))
753 .setAddressType(IpPrefixType.class)
754 .setContextId(l3ContextId)
755 .setContextType(L3Context.class);
756 list.add(addrL3EpUnregBuilder.build());
758 inputBuilder.setAddressEndpointUnreg(list);
759 return inputBuilder.build();
763 private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput createUnregisterEndpointInput(
764 Port port, Neutron neutron) {
765 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder inputBuilder =
766 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder();
767 L2 l2Ep = new L2Builder().setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue()))
768 .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
770 inputBuilder.setL2(ImmutableList.of(l2Ep));
771 // we've registered EP with only first IP so remove only EP with first IP
772 Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
773 if (potentialFirstIp.isPresent()) {
774 FixedIps firstIp = potentialFirstIp.get();
775 L3Address l3Address = resolveL3AddressFromPort(port, firstIp, neutron);
776 L3 l3 = new L3Builder().setIpAddress(l3Address.getIpAddress())
777 .setL3Context(l3Address.getL3Context())
779 inputBuilder.setL3(ImmutableList.of(l3));
781 return inputBuilder.build();
785 private static L3Address resolveL3AddressFromPort(Port port, FixedIps portFixedIPs, Neutron neutron) {
786 Set<Port> routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts());
787 for (Port routerIfacePort : routerIfacePorts) {
788 Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId();
789 // if port is in the same subnet as router interface then we want to use L3Context of
791 if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) {
792 L3ContextId epL3ContextId = new L3ContextId(routerIfacePort.getDeviceId());
793 LOG.trace("Router interface port was found in the same subnet as port have {}", port);
794 return new L3AddressBuilder().setL3Context(epL3ContextId)
795 .setIpAddress(portFixedIPs.getIpAddress())
799 return new L3AddressBuilder().setL3Context(new L3ContextId(port.getNetworkId().getValue()))
800 .setIpAddress(portFixedIPs.getIpAddress())
804 private static ContextId resolveL3ContextForPort(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 LOG.trace("Router interface port was found in the same subnet as port have {}", port);
812 return new ContextId(routerIfacePort.getDeviceId());
815 return new ContextId(port.getNetworkId().getValue());