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