Initial implementation for dynamic SNAT
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / NeutronPortAware.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Set;
15
16 import javax.annotation.Nullable;
17
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
23 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
24 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils;
30 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
31 import org.opendaylight.groupbasedpolicy.util.IidFactory;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpoint;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpointKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
83 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
86
87 import com.google.common.base.Optional;
88 import com.google.common.collect.ImmutableList;
89
90 public class NeutronPortAware implements NeutronAware<Port> {
91
92     private static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
93     public static final InstanceIdentifier<Port> PORT_WILDCARD_IID =
94             InstanceIdentifier.builder(Neutron.class).child(Ports.class).child(Port.class).build();
95     private final DataBroker dataProvider;
96     private final EndpointRegistrator epRegistrator;
97
98     public NeutronPortAware(DataBroker dataProvider, EndpointRegistrator epRegistrator) {
99         this.dataProvider = checkNotNull(dataProvider);
100         this.epRegistrator = checkNotNull(epRegistrator);
101     }
102
103     @Override public void onCreated(Port createdItem, Neutron neutron) {
104         onCreated(createdItem, neutron, true);
105     }
106
107     public void onCreated(Port port, Neutron neutron, boolean addBaseEpMapping) {
108         LOG.trace("created port - {}", port);
109         if (PortUtils.isRouterInterfacePort(port)) {
110             LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
111             // router interface port can have only one IP
112             Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
113             if (!potentialPortIpWithSubnet.isPresent()) {
114                 LOG.warn("Illegal state - router interface port does not contain fixed IPs {}",
115                         port);
116                 return;
117             }
118             FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
119             ContextId routerL3Context = new ContextId(port.getDeviceId());
120             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
121
122             AddressEndpointKey addrEpKey = new AddressEndpointKey(port.getMacAddress().getValue(),
123                 MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
124             UniqueId portId = new UniqueId(port.getUuid().getValue());
125             addBaseEndpointMappings(addrEpKey, portId, rwTx);
126
127             // Add Qrouter and VPProuter port as Endpoint
128             if (port.getAugmentation(PortBindingExtension.class) != null &&
129                 PortUtils.DEVICE_VIF_TYPE.equals(port.getAugmentation(PortBindingExtension.class).getVifType())) {
130                 LOG.trace("Port is QRouter port: {}", port.getUuid().getValue());
131                 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
132                 if (!firstFixedIps.isPresent()) {
133                     LOG.warn("QRouter port does not have an IP address. {}", port);
134                     return;
135                 }
136
137                 FixedIps ipWithSubnet = firstFixedIps.get();
138                 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
139                 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
140                 epgsFromSecGroups.add(NetworkService.EPG_ID);
141
142                 // BUILD BASE ENDPOINT
143                 AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(port, networkContainment,
144                     epgsFromSecGroups);
145                 AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(port, networkContainment,
146                     epgsFromSecGroups, neutron);
147                 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
148
149                 // BUILD ENDPOINT
150                 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder
151                     epInBuilder =
152                     createEndpointRegFromPort(
153                         port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
154                 registerBaseEndpointAndStoreMapping(
155                     ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx, addBaseEpMapping);
156                 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
157             }
158
159             // change L3Context for all EPs with same subnet as router port
160             changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), neutron);
161             // set L3Context as parent for bridge domain which is parent of subnet
162             TenantId tenantId = new TenantId(port.getTenantId().getValue());
163             Optional<Subnet> potentialRouterPortSubnet = SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), neutron.getSubnets());
164             if (!potentialRouterPortSubnet.isPresent()) {
165                 LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}",
166                         port);
167                 return;
168             }
169             Subnet routerPortSubnet = potentialRouterPortSubnet.get();
170             ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
171             ForwardingContext l2Bd = new ForwardingContextBuilder().setContextId(l2BdId)
172                 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
173                 .setParent(MappingUtils.createParent(routerL3Context, MappingUtils.L3_CONTEXT))
174                 .build();
175             rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
176             // set virtual router IP for subnet
177             NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(
178                     routerPortSubnet, neutron);
179             rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
180
181             // does the same for tenant forwarding domains
182             processTenantForwarding(routerPortSubnet, routerL3Context, portIpWithSubnet, tenantId, rwTx);
183
184             DataStoreHelper.submitToDs(rwTx);
185         } else if (PortUtils.isDhcpPort(port)) {
186             // process as normal port but put it to DHCP group
187             LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
188             Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
189             if (!firstFixedIps.isPresent()) {
190                 LOG.warn("DHCP port does not have an IP address. {}", port);
191                 return;
192             }
193             FixedIps ipWithSubnet = firstFixedIps.get();
194             NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
195             List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
196             epgsFromSecGroups.add(NetworkService.EPG_ID);
197
198             // BUILD BASE ENDPOINT
199             AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(port, networkContainment,
200                     epgsFromSecGroups);
201             AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(port, networkContainment,
202                     epgsFromSecGroups, neutron);
203             setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
204
205             // BUILD ENDPOINT
206             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createEndpointRegFromPort(
207                     port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
208
209             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
210             registerBaseEndpointAndStoreMapping(
211                     ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx, addBaseEpMapping);
212             registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
213             DataStoreHelper.submitToDs(rwTx);
214         } else if (PortUtils.isNormalPort(port)) {
215             LOG.trace("Port is normal port: {}", port.getUuid().getValue());
216             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = null;
217             AddressEndpointRegBuilder l2BaseEp;
218             AddressEndpointRegBuilder l3BaseEp = null;
219             Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
220             List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
221             epgsFromSecGroups.add(NetworkClient.EPG_ID);
222             if (firstFixedIps.isPresent()) {
223                 // endpoint has only one network containment therefore only first IP is used
224                 FixedIps ipWithSubnet = firstFixedIps.get();
225                 NetworkDomainId containment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
226                 epInBuilder = createEndpointRegFromPort(port, ipWithSubnet, containment, epgsFromSecGroups, neutron);
227                 l2BaseEp = createBasicMacAddrEpInputBuilder(port,
228                         containment, epgsFromSecGroups);
229                 l3BaseEp = createBasicL3AddrEpInputBuilder(port, containment, epgsFromSecGroups, neutron);
230                 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
231             } else {
232                 NetworkDomainId containment = new NetworkDomainId(port.getNetworkId().getValue());
233                 epInBuilder = createEndpointRegFromPort(port, null, containment, epgsFromSecGroups, neutron);
234                 l2BaseEp = createBasicMacAddrEpInputBuilder(port, containment, epgsFromSecGroups);
235             }
236             List<AddressEndpointReg> baseEpRegs = new ArrayList<>();
237             baseEpRegs.add(l2BaseEp.build());
238             if (l3BaseEp != null) {
239                 baseEpRegs.add(l3BaseEp.build());
240             }
241             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
242             registerBaseEndpointAndStoreMapping(baseEpRegs, port, rwTx, addBaseEpMapping);
243             registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
244             DataStoreHelper.submitToDs(rwTx);
245         } else if (PortUtils.isRouterGatewayPort(port)) {
246             // do nothing because actual trigger is attaching of port to router
247             LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
248         } else if (PortUtils.isFloatingIpPort(port)) {
249             // do nothing because trigger is floating IP
250             LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
251         } else {
252             LOG.warn("Unknown port: {}", port);
253         }
254     }
255
256     private void setParentChildRelationshipForEndpoints(AddressEndpointRegBuilder parentEp,
257             AddressEndpointRegBuilder childEp) {
258         childEp.setParentEndpointChoice(new ParentEndpointCaseBuilder().setParentEndpoint(
259                 ImmutableList.<ParentEndpoint>of(createParentEndpoint(parentEp))).build());
260         parentEp.setChildEndpoint(ImmutableList.<ChildEndpoint>of(createChildEndpoint(childEp)));
261     }
262
263     @Deprecated
264     private void processTenantForwarding(Subnet routerPortSubnet, ContextId routerL3Context, FixedIps portIpWithSubnet,
265             TenantId tenantId, ReadWriteTransaction rwTx) {
266         L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
267         L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(new L3ContextId(routerL3Context)).build();
268         rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
269         // set virtual router IP for subnet
270         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnet = NeutronSubnetAware.createTenantSubnet(
271                 routerPortSubnet, portIpWithSubnet.getIpAddress());
272         rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet);
273     }
274
275     /**
276      * Registers endpoint from {@link Port} and method parameters.
277      * Always creates registration input for L2 endpoint.
278      * Creates registration input for L3 endpoint if fixedIps argument is not null.
279      */
280     @Deprecated
281     private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createEndpointRegFromPort(
282             Port port, FixedIps fixedIps, NetworkDomainId networkContainment, List<EndpointGroupId> endpointGroupIds, Neutron neutron) {
283         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createBasicEndpointInputBuilder(
284                 port).setNetworkContainment(networkContainment);
285         if (fixedIps != null) {
286             L3Address l3Address = resolveL3AddressFromPort(port, fixedIps, neutron);
287             epInBuilder.setL3Address(ImmutableList.of(l3Address));
288         }
289         epInBuilder.setEndpointGroups(endpointGroupIds);
290         return epInBuilder;
291     }
292
293     private void changeL3ContextForEpsInSubnet(Uuid subnetUuid, Neutron neutron) {
294         if (neutron == null) {
295             LOG.debug("No new data are written, there is no L3 context in subnet {} to update", subnetUuid);
296             return;
297         }
298         Set<Port> portsInSameSubnet = PortUtils.findPortsBySubnet(subnetUuid, neutron.getPorts());
299         for (Port portInSameSubnet : portsInSameSubnet) {
300             if (PortUtils.isNormalPort(portInSameSubnet) || PortUtils.isDhcpPort(portInSameSubnet)
301                 || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
302                 // endpoints are created only from neutron normal port or DHCP port
303                 Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(portInSameSubnet);
304                 if (firstFixedIps.isPresent()) {
305                     // endpoint has only one network containment therefore only first IP is used
306                     FixedIps ipWithSubnet = firstFixedIps.get();
307                     List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
308                     if (PortUtils.isDhcpPort(portInSameSubnet) || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
309                         endpointGroupIds.add(NetworkService.EPG_ID);
310                     } else if (PortUtils.isNormalPort(portInSameSubnet)) {
311                         endpointGroupIds.add(NetworkClient.EPG_ID);
312                     }
313                     NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
314                     AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(portInSameSubnet,
315                             networkContainment, endpointGroupIds);
316                     AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(portInSameSubnet,
317                             networkContainment, endpointGroupIds, neutron);
318                     setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
319                     AddressEndpointUnreg addrEpUnreg = new AddressEndpointUnregBuilder().setAddress(l3BaseEp.getAddress())
320                         .setAddressType(l3BaseEp.getAddressType())
321                         .setContextId(new ContextId(portInSameSubnet.getNetworkId().getValue()))
322                         .setContextType(l3BaseEp.getContextType())
323                         .build();
324                     epRegistrator.unregisterEndpoint(addrEpUnreg);
325                     RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder()
326                         .setAddressEndpointReg(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build())).build();
327                     epRegistrator.registerEndpoint(regBaseEpInput);
328
329                     modifyL3ContextForEndpoints(portInSameSubnet, ipWithSubnet, l3BaseEp.getContextId());
330                 }
331             }
332         }
333     }
334
335     private ChildEndpoint createChildEndpoint(AddressEndpointRegBuilder builder) {
336         return new ChildEndpointBuilder().setAddress(builder.getAddress())
337             .setAddressType(builder.getAddressType())
338             .setContextId(builder.getContextId())
339             .setContextType(builder.getContextType())
340             .build();
341     }
342
343     private ParentEndpoint createParentEndpoint(AddressEndpointRegBuilder builder) {
344         return new ParentEndpointBuilder().setAddress(builder.getAddress())
345             .setAddressType(builder.getAddressType())
346             .setContextId(builder.getContextId())
347             .setContextType(builder.getContextType())
348             .build();
349     }
350
351     @Deprecated
352     private void modifyL3ContextForEndpoints(Port port, FixedIps resolvedPortFixedIp, ContextId newContextId) {
353         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createBasicEndpointInputBuilder(port);
354         epInBuilder.setNetworkContainment(new NetworkDomainId(resolvedPortFixedIp.getSubnetId().getValue()));
355         L3Address l3Address = new L3AddressBuilder().setL3Context(new L3ContextId(newContextId))
356             .setIpAddress(resolvedPortFixedIp.getIpAddress())
357             .build();
358         epInBuilder.setL3Address(ImmutableList.of(l3Address));
359         List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
360         epgsFromSecGroups.add(NetworkClient.EPG_ID);
361         epInBuilder.setEndpointGroups(epgsFromSecGroups);
362         epRegistrator.registerEndpoint(epInBuilder.build());
363         // unregister L3EP
364         L3ContextId oldL3Context = new L3ContextId(port.getNetworkId().getValue());
365         L3 l3 = new L3Builder().setL3Context(oldL3Context).setIpAddress(resolvedPortFixedIp.getIpAddress()).build();
366         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput epUnreg = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder().setL3(
367                 ImmutableList.of(l3))
368             .build();
369         epRegistrator.unregisterEndpoint(epUnreg);
370     }
371
372     private AddressEndpointRegBuilder createBasicMacAddrEpInputBuilder(Port port,
373             NetworkDomainId networkContainment, @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
374         AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
375             .setAddress(port.getMacAddress().getValue())
376             .setAddressType(MacAddressType.class)
377             .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
378             .setContextId(new ContextId(port.getNetworkId().getValue()))
379             .setTenant(new TenantId(port.getTenantId().getValue()))
380             .setTimestamp(System.currentTimeMillis());
381         List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
382         addrEpbuilder.setEndpointGroup(epgs);
383         if (networkContainment != null) {
384             addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment(
385                     new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
386                         .setNetworkDomainType(MappingUtils.SUBNET)
387                         .build()).build());
388         }
389         return addrEpbuilder;
390     }
391
392     private AddressEndpointRegBuilder createBasicL3AddrEpInputBuilder(Port port, NetworkDomainId networkContainment,
393             @Nullable List<EndpointGroupId> endpointGroupsToAdd, Neutron neutron) {
394         Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
395         if (!firstFixedIps.isPresent()) {
396             throw new IllegalStateException("Failed to resolve FixedIps for port " + port.getKey()
397                     + ". Cannot register L3 Address endpoint.");
398         }
399         ContextId resolveL3ContextForPort = resolveL3ContextForPort(port, port.getFixedIps().get(0), neutron);
400
401         AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
402             .setAddress(MappingUtils.ipAddressToStringIpPrefix(firstFixedIps.get().getIpAddress()))
403             .setAddressType(IpPrefixType.class)
404             .setContextType(MappingUtils.L3_CONTEXT)
405             .setContextId(resolveL3ContextForPort)
406             .setTenant(new TenantId(port.getTenantId().getValue()))
407             .setTimestamp(System.currentTimeMillis());
408         List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
409         addrEpbuilder.setEndpointGroup(epgs);
410         if (networkContainment != null) {
411             addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment(
412                     new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
413                         .setNetworkDomainType(MappingUtils.SUBNET)
414                         .build()).build());
415         }
416         return addrEpbuilder;
417     }
418
419     private List<EndpointGroupId> concatEndpointGroups(List<Uuid> securityGroups,
420             @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
421         List<EndpointGroupId> epgs = new ArrayList<>();
422         if (securityGroups != null) {
423             for (Uuid sgId : securityGroups) {
424                 epgs.add(new EndpointGroupId(sgId.getValue()));
425             }
426         }
427         if (endpointGroupsToAdd != null) {
428             epgs.addAll(endpointGroupsToAdd);
429         }
430         return epgs;
431     }
432
433     @Deprecated
434     private static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createBasicEndpointInputBuilder(
435             Port port) {
436         return new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder().setL2Context(
437                 new L2BridgeDomainId(port.getNetworkId().getValue()))
438             .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
439             .setTenant(new TenantId(port.getTenantId().getValue()))
440             .setTimestamp(System.currentTimeMillis());
441     }
442
443     private static List<EndpointGroupId> resolveEpgIdsFromSecGroups(@Nullable List<Uuid> securityGroups) {
444         List<EndpointGroupId> epgIds = new ArrayList<>();
445         if ((securityGroups == null || securityGroups.isEmpty())) {
446             return epgIds;
447         }
448         for (Uuid secGrp : securityGroups) {
449             epgIds.add(new EndpointGroupId(secGrp.getValue()));
450         }
451         return epgIds;
452     }
453
454     @Deprecated
455     private void registerEndpointAndStoreMapping(
456             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput regEpInput,
457             Port port, ReadWriteTransaction rwTx) {
458         boolean isRegisteredEndpoint = epRegistrator.registerEndpoint(regEpInput);
459         if (!isRegisteredEndpoint) {
460             LOG.error("Failed to register an endpoint: {}", regEpInput);
461             return;
462         }
463         UniqueId portId = new UniqueId(port.getUuid().getValue());
464         EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress(
465                 port.getMacAddress().getValue()));
466         LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid()
467             .getValue(), port.getDeviceOwner(), epKey);
468         EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
469         rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort, true);
470         PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
471         rwTx.put(LogicalDatastoreType.OPERATIONAL,
472                 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint,
473                 true);
474     }
475
476     @Deprecated
477     private void unregisterEndpointAndRemoveMapping(
478             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput unregEpInput,
479             Port port, ReadWriteTransaction rwTx) {
480         boolean isUnregisteredEndpoint = epRegistrator.unregisterEndpoint(unregEpInput);
481         if (isUnregisteredEndpoint) {
482             UniqueId portId = new UniqueId(port.getUuid().getValue());
483             EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress(
484                     port.getMacAddress().getValue()));
485             LOG.trace("Removing Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid()
486                 .getValue(), port.getDeviceOwner(), epKey);
487             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
488                     NeutronGbpIidFactory.endpointByPortIid(portId), rwTx);
489             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
490                     NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
491         }
492     }
493
494     private void registerBaseEndpointAndStoreMapping(List<AddressEndpointReg> addrEpRegs, Port port,
495             WriteTransaction wTx, boolean addBaseEpMappings) {
496         RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder().setAddressEndpointReg(addrEpRegs)
497             .build();
498
499         boolean isRegisteredBaseEndpoint = epRegistrator.registerEndpoint(regBaseEpInput);
500         if (!isRegisteredBaseEndpoint) {
501             LOG.error("Failed to register an address endpoint: {}", addrEpRegs);
502             return;
503         }
504         for (AddressEndpointReg addrEpReg : addrEpRegs) {
505             if (MappingUtils.L2_BRDIGE_DOMAIN.equals(addrEpReg.getContextType()) && addBaseEpMappings) {
506                 UniqueId portId = new UniqueId(port.getUuid().getValue());
507                 LOG.trace("Adding Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
508                         port.getUuid());
509                 AddressEndpointKey addrEpKey = new AddressEndpointKey(addrEpReg.getAddress(),
510                         addrEpReg.getAddressType(), addrEpReg.getContextId(), addrEpReg.getContextType());
511                 addBaseEndpointMappings(addrEpKey, portId, wTx);
512             }
513         }
514     }
515
516     private void addBaseEndpointMappings(AddressEndpointKey addrEpKey, UniqueId portId, WriteTransaction wTx) {
517         BaseEndpointByPort baseEndpointByPort = MappingFactory.createBaseEndpointByPort(addrEpKey, portId);
518         wTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.baseEndpointByPortIid(portId),
519                 baseEndpointByPort, true);
520         PortByBaseEndpoint portByBaseEndpoint = MappingFactory.createPortByBaseEndpoint(portId, addrEpKey);
521         wTx.put(LogicalDatastoreType.OPERATIONAL,
522                 NeutronGbpIidFactory.portByBaseEndpointIid(new PortByBaseEndpointKey(
523                         portByBaseEndpoint.getKey())), portByBaseEndpoint, true);
524     }
525
526     private void unregisterEndpointAndRemoveMapping(UnregisterEndpointInput baseEpUnreg, Port port,
527             ReadWriteTransaction rwTx, boolean removeBaseEpMappings) {
528         boolean isUnregisteredBaseEndpoint = epRegistrator.unregisterEndpoint(baseEpUnreg);
529         if (isUnregisteredBaseEndpoint) {
530             UniqueId portId = new UniqueId(port.getUuid().getValue());
531             PortByBaseEndpointKey portByBaseEndpointKey = new PortByBaseEndpointKey(port.getMacAddress().getValue(),
532                     MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
533             LOG.trace("Removing Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
534                     port.getUuid().getValue(), port.getDeviceOwner(), portByBaseEndpointKey);
535             if (removeBaseEpMappings) {
536                 removeBaseEndpointMappings(portByBaseEndpointKey, portId, rwTx);
537             }
538         }
539     }
540
541     private void removeBaseEndpointMappings(PortByBaseEndpointKey portByBaseEndpointKey, UniqueId portId, ReadWriteTransaction rwTx) {
542         DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
543                 NeutronGbpIidFactory.baseEndpointByPortIid(portId), rwTx);
544         DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
545                 NeutronGbpIidFactory.portByBaseEndpointIid(portByBaseEndpointKey), rwTx);
546     }
547
548     @Override
549     public void onUpdated(Port oldPort, Port newPort, Neutron oldNeutron, Neutron newNeutron) {
550         LOG.trace("updated port - OLD: {}\nNEW: {}", oldPort, newPort);
551         onDeleted(oldPort, oldNeutron, newNeutron, false);
552         onCreated(newPort, newNeutron, false);
553     }
554
555     @Override public void onDeleted(Port deletedItem, Neutron oldNeutron, Neutron newNeutron) {
556         onDeleted(deletedItem, oldNeutron, newNeutron, true);
557     }
558
559     public void onDeleted(Port port, Neutron oldNeutron, Neutron newNeutron, boolean removeBaseEpMapping) {
560         LOG.trace("deleted port - {}", port);
561         if (PortUtils.isRouterInterfacePort(port)) {
562             LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
563             // router interface port can have only one IP
564             Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
565             if (!potentialPortIpWithSubnet.isPresent()) {
566                 LOG.warn("Illegal state - router interface port does not contain fixed IPs {}",
567                         port);
568                 return;
569             }
570             FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
571             L3ContextId l3Context = new L3ContextId(port.getNetworkId().getValue());
572             // change L3Context for all new EPs with same subnet as router port
573             changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), newNeutron);
574             // set L3Context as parent for bridge domain which is parent of subnet
575             TenantId tenantId = new TenantId(port.getTenantId().getValue());
576             Optional<Subnet> potentialRouterPortSubnet = SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(),
577                     oldNeutron.getSubnets());
578             if (!potentialRouterPortSubnet.isPresent()) {
579                 LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", port);
580                 return;
581             }
582             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
583             Subnet routerPortSubnet = potentialRouterPortSubnet.get();
584             modifyForwardingOnDelete(routerPortSubnet, l3Context, tenantId, rwTx);
585             ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
586             ForwardingContext fwdCtx = new ForwardingContextBuilder().setContextId(l2BdId)
587                 .setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
588                 .setParent(MappingUtils.createParent(l3Context, MappingUtils.L3_CONTEXT))
589                 .build();
590             rwTx.merge(LogicalDatastoreType.CONFIGURATION,
591                     L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
592             NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron);
593             rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()),
594                     subnet);
595             unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
596             unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping);
597             DataStoreHelper.submitToDs(rwTx);
598         } else if (PortUtils.isDhcpPort(port)) {
599             LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
600             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
601             unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
602             unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping);
603             DataStoreHelper.submitToDs(rwTx);
604         } else if (PortUtils.isNormalPort(port)) {
605             LOG.trace("Port is normal port: {}", port.getUuid().getValue());
606             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
607             unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
608             unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping);
609             DataStoreHelper.submitToDs(rwTx);
610         } else if (PortUtils.isRouterGatewayPort(port)) {
611             // do nothing because actual trigger is detaching of port from router
612             LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
613         } else if (PortUtils.isFloatingIpPort(port)) {
614             // do nothing because trigger is floating IP
615             LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
616         } else {
617             LOG.warn("Unknown port: {}", port);
618         }
619     }
620
621     @Deprecated
622     private void modifyForwardingOnDelete(Subnet routerPortSubnet, L3ContextId l3contextId, TenantId tenantId, ReadWriteTransaction rwTx) {
623         L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
624         L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(l3contextId).build();
625         rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd);
626         // remove virtual router IP for subnet
627         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet tenantSubnet = NeutronSubnetAware.createTenantSubnet(routerPortSubnet, null);
628         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, tenantSubnet.getId()), tenantSubnet);
629     }
630
631     private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput createUnregisterBaseEndpointInput(
632             Port port, Neutron neutron) {
633         UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
634         List<AddressEndpointUnreg> list = new ArrayList<>();
635         AddressEndpointUnregBuilder addrL2EpUnregBuilder = new AddressEndpointUnregBuilder();
636         addrL2EpUnregBuilder.setAddress(port.getMacAddress().getValue())
637             .setAddressType(MacAddressType.class)
638             .setContextId(new ContextId(port.getNetworkId().getValue()))
639             .setContextType(MappingUtils.L2_BRDIGE_DOMAIN);
640         list.add(addrL2EpUnregBuilder.build());
641         Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
642         if (potentialFirstIp.isPresent()) {
643             ContextId l3ContextId = resolveL3ContextForPort(port, potentialFirstIp.get(), neutron);
644             AddressEndpointUnregBuilder addrL3EpUnregBuilder = new AddressEndpointUnregBuilder();
645             addrL3EpUnregBuilder.setAddress(MappingUtils.ipAddressToStringIpPrefix(potentialFirstIp.get().getIpAddress()))
646                 .setAddressType(IpPrefixType.class)
647                 .setContextId(l3ContextId)
648                 .setContextType(L3Context.class);
649             list.add(addrL3EpUnregBuilder.build());
650         }
651         inputBuilder.setAddressEndpointUnreg(list);
652         return inputBuilder.build();
653     }
654
655     @Deprecated
656     private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput createUnregisterEndpointInput(
657             Port port, Neutron neutron) {
658         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder inputBuilder =
659                 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder();
660         L2 l2Ep = new L2Builder().setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue()))
661             .setMacAddress(new MacAddress(port.getMacAddress().getValue()))
662             .build();
663         inputBuilder.setL2(ImmutableList.of(l2Ep));
664         // we've registered EP with only first IP so remove only EP with first IP
665         Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
666         if (potentialFirstIp.isPresent()) {
667             FixedIps firstIp = potentialFirstIp.get();
668             L3Address l3Address = resolveL3AddressFromPort(port, firstIp, neutron);
669             L3 l3 = new L3Builder().setIpAddress(l3Address.getIpAddress())
670                 .setL3Context(l3Address.getL3Context())
671                 .build();
672             inputBuilder.setL3(ImmutableList.of(l3));
673         }
674         return inputBuilder.build();
675     }
676
677     @Deprecated
678     private static L3Address resolveL3AddressFromPort(Port port, FixedIps portFixedIPs, Neutron neutron) {
679         Set<Port> routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts());
680         for (Port routerIfacePort : routerIfacePorts) {
681             Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId();
682             // if port is in the same subnet as router interface then we want to use L3Context of
683             // router
684             if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) {
685                 L3ContextId epL3ContextId = new L3ContextId(routerIfacePort.getDeviceId());
686                 LOG.trace("Router interface port was found in the same subnet as port have {}", port);
687                 return new L3AddressBuilder().setL3Context(epL3ContextId)
688                     .setIpAddress(portFixedIPs.getIpAddress())
689                     .build();
690             }
691         }
692         return new L3AddressBuilder().setL3Context(new L3ContextId(port.getNetworkId().getValue()))
693             .setIpAddress(portFixedIPs.getIpAddress())
694             .build();
695     }
696
697     private static ContextId resolveL3ContextForPort(Port port, FixedIps portFixedIPs, Neutron neutron) {
698         Set<Port> routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts());
699         for (Port routerIfacePort : routerIfacePorts) {
700             Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId();
701             // if port is in the same subnet as router interface then we want to use L3Context of
702             // router
703             if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) {
704                 LOG.trace("Router interface port was found in the same subnet as port have {}", port);
705                 return new ContextId(routerIfacePort.getDeviceId());
706             }
707         }
708         return new ContextId(port.getNetworkId().getValue());
709     }
710 }