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