Bug 3588 getting of MAC based on ARP
[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.Collection;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.concurrent.ExecutionException;
20
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
31 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
32 import org.opendaylight.groupbasedpolicy.util.IidFactory;
33 import org.opendaylight.neutron.spi.INeutronPortAware;
34 import org.opendaylight.neutron.spi.NeutronPort;
35 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
36 import org.opendaylight.neutron.spi.NeutronSecurityRule;
37 import org.opendaylight.neutron.spi.Neutron_IPs;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInputBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.floating.ip.ports.EndpointByFloatingIpPort;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router._interface.ports.EndpointByRouterInterfacePort;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router.gateway.ports.EndpointByRouterGatewayPort;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.l3.endpoints.ExternalGatewayAsL3Endpoint;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.floating.ip.ports.by.endpoints.FloatingIpPortByEndpoint;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router._interface.ports.by.endpoints.RouterInterfacePortByEndpoint;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router.gateway.ports.by.endpoints.RouterGatewayPortByEndpoint;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
83 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
84 import org.opendaylight.yangtools.yang.common.RpcResult;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
87
88 import com.google.common.base.Function;
89 import com.google.common.base.Optional;
90 import com.google.common.base.Strings;
91 import com.google.common.collect.Collections2;
92 import com.google.common.collect.ImmutableList;
93
94 public class NeutronPortAware implements INeutronPortAware {
95
96     public static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
97     private static final String DEVICE_OWNER_DHCP = "network:dhcp";
98     private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
99     private static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway";
100     private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
101     private static final int DHCP_SERVER_PORT = 67;
102     private static final int DNS_SERVER_PORT = 53;
103     private final DataBroker dataProvider;
104     private final EndpointService epService;
105     private final static Map<String, UniqueId> floatingIpPortByDeviceId = new HashMap<>();
106
107     public NeutronPortAware(DataBroker dataProvider, EndpointService epService) {
108         this.dataProvider = checkNotNull(dataProvider);
109         this.epService = checkNotNull(epService);
110     }
111
112     /**
113      * @see org.opendaylight.neutron.spi.INeutronPortAware#canCreatePort(org.opendaylight.neutron.spi.NeutronPort)
114      */
115     @Override
116     public int canCreatePort(NeutronPort port) {
117         LOG.trace("canCreatePort - {}", port);
118         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
119         List<Neutron_IPs> fixedIPs = port.getFixedIPs();
120         if (fixedIPs != null && fixedIPs.size() > 1) {
121             LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
122             return StatusCode.BAD_REQUEST;
123         }
124         return StatusCode.OK;
125     }
126
127     /**
128      * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortCreated(org.opendaylight.neutron.spi.NeutronPort)
129      */
130     @Override
131     public void neutronPortCreated(NeutronPort port) {
132         LOG.trace("neutronPortCreated - {}", port);
133         if (isRouterInterfacePort(port)) {
134             LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
135                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
136             return;
137         }
138         if (isRouterGatewayPort(port)) {
139             LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
140                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
141             return;
142         }
143         if (isFloatingIpPort(port)) {
144             LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
145             floatingIpPortByDeviceId.put(port.getDeviceID(), new UniqueId(port.getID()));
146             return;
147         }
148         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
149         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
150         if (isDhcpPort(port)) {
151             LOG.trace("Port is DHCP port. - {}", port.getID());
152             List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, null, rwTx);
153             if (dhcpSecRules == null) {
154                 rwTx.cancel();
155                 return;
156             }
157
158             for (NeutronSecurityRule dhcpSecRule : dhcpSecRules) {
159                 boolean isDhcpSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(dhcpSecRule, rwTx);
160                 if (!isDhcpSecRuleAdded) {
161                     rwTx.cancel();
162                     return;
163                 }
164             }
165         } else {
166             List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
167             if (secGroups != null) {
168                 for (NeutronSecurityGroup secGroup : secGroups) {
169                     EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
170                     Optional<EndpointGroup> potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
171                             IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
172                     if (!potentialEpg.isPresent()) {
173                         boolean isSecGroupCreated = NeutronSecurityGroupAware.addNeutronSecurityGroup(secGroup, rwTx);
174                         if (!isSecGroupCreated) {
175                             rwTx.cancel();
176                             return;
177                         }
178                         if (containsSecRuleWithRemoteSecGroup(secGroup)) {
179                             List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, epgId, rwTx);
180                             if (dhcpSecRules == null) {
181                                 rwTx.cancel();
182                                 return;
183                             }
184                             List<NeutronSecurityRule> routerSecRules = NeutronRouterAware.createRouterSecRules(port, epgId, rwTx);
185                             if (routerSecRules == null) {
186                                 rwTx.cancel();
187                                 return;
188                             }
189                         }
190                     } else {
191                         List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
192                         if (secRules != null) {
193                             for (NeutronSecurityRule secRule : secRules) {
194                                 NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx);
195                             }
196                         }
197                     }
198                 }
199             }
200         }
201         boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService);
202         if (!isNeutronPortCreated) {
203             rwTx.cancel();
204             return;
205         }
206
207         DataStoreHelper.submitToDs(rwTx);
208     }
209
210     public static boolean addNeutronPort(NeutronPort port, ReadWriteTransaction rwTx, EndpointService epService) {
211         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
212         L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
213         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
214         boolean isFwCtxValid = validateForwardingCtx(fwCtx);
215         if (!isFwCtxValid) {
216             return false;
217         }
218         EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
219         addNeutronGbpMapping(port, epKey, rwTx);
220
221         try {
222             RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
223             RpcResult<Void> rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
224             if (!rpcResult.isSuccessful()) {
225                 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
226                 return false;
227             }
228         } catch (InterruptedException | ExecutionException e) {
229             LOG.error("addNeutronPort failed. {}", port, e);
230             return false;
231         }
232         return true;
233     }
234
235     public static boolean addL3EndpointForExternalGateway(TenantId tenantId, L3ContextId l3ContextId,
236             IpAddress ipAddress, NetworkDomainId networkContainment, ReadWriteTransaction rwTx) {
237
238         EndpointL3Key epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
239         addNeutronExtGwGbpMapping(epL3Key, rwTx);
240         List<EndpointGroupId> epgIds = new ArrayList<>();
241         // each EP has to be in EPG ANY, except dhcp and router
242         epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
243         epgIds.add(MappingUtils.EPG_ROUTER_ID);
244         EndpointL3 epL3 = createL3Endpoint(tenantId, epL3Key, epgIds, networkContainment);
245         InstanceIdentifier<EndpointL3> iid_l3 = IidFactory.l3EndpointIid(l3ContextId, ipAddress);
246         rwTx.put(LogicalDatastoreType.OPERATIONAL, iid_l3, epL3, true);
247         return true;
248     }
249
250     private static void addNeutronExtGwGbpMapping(EndpointL3Key epL3Key, ReadWriteTransaction rwTx) {
251             ExternalGatewayAsL3Endpoint externalGatewayL3Endpoint = MappingFactory.createExternalGatewayByL3Endpoint(epL3Key);
252             rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()),
253                     externalGatewayL3Endpoint, true);
254     }
255
256     private static void addNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
257         UniqueId portId = new UniqueId(port.getID());
258         if (isRouterInterfacePort(port)) {
259             LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
260             EndpointByRouterInterfacePort endpointByPort = MappingFactory.createEndpointByRouterInterfacePort(epKey,
261                     portId);
262             rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterInterfacePortIid(portId),
263                     endpointByPort, true);
264             RouterInterfacePortByEndpoint portByEndpoint = MappingFactory.createRouterInterfacePortByEndpoint(portId,
265                     epKey);
266             rwTx.put(LogicalDatastoreType.OPERATIONAL,
267                     NeutronGbpIidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
268                     portByEndpoint, true);
269         } else if (isRouterGatewayPort(port)) {
270             LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
271             EndpointByRouterGatewayPort endpointByPort = MappingFactory.createEndpointByRouterGatewayPort(epKey, portId);
272             rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterGatewayPortIid(portId),
273                     endpointByPort, true);
274             RouterGatewayPortByEndpoint portByEndpoint = MappingFactory.createRouterGatewayPortByEndpoint(portId, epKey);
275             rwTx.put(LogicalDatastoreType.OPERATIONAL,
276                     NeutronGbpIidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
277                     portByEndpoint, true);
278         } else if (isFloatingIpPort(port)) {
279             LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
280             EndpointByFloatingIpPort endpointByPort = MappingFactory.createEndpointByFloatingIpPort(epKey, portId);
281             rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByFloatingIpPortIid(portId),
282                     endpointByPort, true);
283             FloatingIpPortByEndpoint portByEndpoint = MappingFactory.createFloatingIpPortByEndpoint(portId, epKey);
284             rwTx.put(LogicalDatastoreType.OPERATIONAL,
285                     NeutronGbpIidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
286                     portByEndpoint, true);
287         } else {
288             LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
289                     port.getDeviceOwner(), epKey);
290             EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
291             rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort, true);
292             PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
293             rwTx.put(LogicalDatastoreType.OPERATIONAL,
294                     NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint, true);
295         }
296     }
297
298     public static boolean addL3PrefixEndpoint(L3ContextId l3ContextId, IpPrefix ipPrefix, IpAddress ipAddress, TenantId tenantId,
299             ReadWriteTransaction rwTx, EndpointService epService) {
300
301         EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey( ipPrefix, l3ContextId);
302
303         EndpointL3Key epL3Key = null;
304         List<EndpointL3Key> l3Gateways = new ArrayList<>();
305         if (ipAddress != null) {
306             epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
307             l3Gateways.add(epL3Key);
308         }
309
310
311         try {
312             RegisterL3PrefixEndpointInput registerL3PrefixEpRpcInput = createRegisterL3PrefixEndpointInput(epL3PrefixKey, l3Gateways,tenantId);
313
314             RpcResult<Void> rpcResult = epService.registerL3PrefixEndpoint(registerL3PrefixEpRpcInput).get();
315             if (!rpcResult.isSuccessful()) {
316                 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerL3PrefixEpRpcInput);
317                 return false;
318             }
319         } catch (InterruptedException | ExecutionException e) {
320             LOG.error("addPort - RPC invocation failed.", e);
321             return false;
322         }
323         return true;
324
325     }
326
327     private static boolean validateForwardingCtx(ForwardingCtx fwCtx) {
328         if (fwCtx.getL2FloodDomain() == null) {
329             LOG.warn("Illegal state - l2-flood-domain does not exist.");
330             return false;
331         }
332         if (fwCtx.getL2BridgeDomain() == null) {
333             LOG.warn("Illegal state - l2-bridge-domain does not exist.");
334             return false;
335         }
336         if (fwCtx.getL3Context() == null) {
337             LOG.warn("Illegal state - l3-context does not exist.");
338             return false;
339         }
340         return true;
341     }
342
343     private List<NeutronSecurityRule> createDhcpSecRules(NeutronPort port, EndpointGroupId consumerEpgId, ReadTransaction rTx) {
344         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
345         Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
346         if (firstIp == null) {
347             LOG.warn("Illegal state - DHCP port does not have an IP address.");
348             return null;
349         }
350         IpAddress ipAddress = Utils.createIpAddress(firstIp.getIpAddress());
351         boolean isIPv4Ethertype = ipAddress.getIpv4Address() == null ? false : true;
352         List<NeutronSecurityRule> rules = new ArrayList<>();
353         rules.add(createDhcpIngressSecRule(port.getID(), tenantId, isIPv4Ethertype, consumerEpgId));
354         rules.add(createDnsSecRule(port.getID(), tenantId, isIPv4Ethertype, consumerEpgId));
355         rules.add(createUdpEgressSecRule(port.getID(), tenantId, isIPv4Ethertype, consumerEpgId));
356         rules.add(createIcmpSecRule(port.getID(), tenantId, isIPv4Ethertype, consumerEpgId, true));
357         rules.add(createIcmpSecRule(port.getID(), tenantId, isIPv4Ethertype, consumerEpgId, false));
358         return rules;
359     }
360
361     private NeutronSecurityRule createDhcpIngressSecRule(String ruleUuid, TenantId tenantId, boolean isIPv4Ethertype, EndpointGroupId consumerEpgId) {
362         NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
363         dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
364         dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
365         if (consumerEpgId != null) {
366             dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
367         }
368         dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "_dhcp__" + ruleUuid);
369         dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
370         dhcpSecRule.setSecurityRulePortMin(DHCP_SERVER_PORT);
371         dhcpSecRule.setSecurityRulePortMax(DHCP_SERVER_PORT);
372         dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
373         if (isIPv4Ethertype) {
374             dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
375         } else {
376             dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
377         }
378         return dhcpSecRule;
379     }
380
381     private NeutronSecurityRule createUdpEgressSecRule(String ruleUuid, TenantId tenantId, boolean isIPv4Ethertype, EndpointGroupId consumerEpgId) {
382         NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
383         dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
384         dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
385         if (consumerEpgId != null) {
386             dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
387         }
388         dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "_udp__" + ruleUuid);
389         dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
390         dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
391         if (isIPv4Ethertype) {
392             dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
393         } else {
394             dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
395         }
396         return dhcpSecRule;
397     }
398
399     private NeutronSecurityRule createDnsSecRule(String ruleUuid, TenantId tenantId, boolean isIPv4Ethertype, EndpointGroupId consumerEpgId) {
400         NeutronSecurityRule dnsSecRule = new NeutronSecurityRule();
401         dnsSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
402         dnsSecRule.setSecurityRuleTenantID(tenantId.getValue());
403         if (consumerEpgId != null) {
404             dnsSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
405         }
406         dnsSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "_dns__" + ruleUuid);
407         dnsSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
408         dnsSecRule.setSecurityRulePortMin(DNS_SERVER_PORT);
409         dnsSecRule.setSecurityRulePortMax(DNS_SERVER_PORT);
410         dnsSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
411         if (isIPv4Ethertype) {
412             dnsSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
413         } else {
414             dnsSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
415         }
416         return dnsSecRule;
417     }
418
419     private NeutronSecurityRule createIcmpSecRule(String ruleUuid, TenantId tenantId, boolean isIPv4Ethertype, EndpointGroupId consumerEpgId,
420             boolean isEgress) {
421         NeutronSecurityRule icmpSecRule = new NeutronSecurityRule();
422         icmpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
423         icmpSecRule.setSecurityRuleTenantID(tenantId.getValue());
424         if (consumerEpgId != null) {
425             icmpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
426         }
427         if (isEgress) {
428             icmpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "_icmp__" + ruleUuid);
429             icmpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
430         } else {
431             icmpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "_icmp__" + ruleUuid);
432             icmpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
433         }
434         icmpSecRule.setSecurityRuleProtocol(NeutronUtils.ICMP);
435         if (isIPv4Ethertype) {
436             icmpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
437         } else {
438             icmpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
439         }
440         return icmpSecRule;
441     }
442
443     /**
444      * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort,
445      *      org.opendaylight.neutron.spi.NeutronPort)
446      */
447     @Override
448     public int canUpdatePort(NeutronPort delta, NeutronPort original) {
449         LOG.trace("canUpdatePort - delta: {} original: {}", delta, original);
450         if (delta.getFixedIPs() == null || delta.getFixedIPs().isEmpty()) {
451             return StatusCode.OK;
452         }
453         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
454         List<Neutron_IPs> fixedIPs = delta.getFixedIPs();
455         if (fixedIPs != null && fixedIPs.size() > 1) {
456             LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
457             return StatusCode.BAD_REQUEST;
458         }
459         return StatusCode.OK;
460     }
461
462     /**
463      * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortUpdated(org.opendaylight.neutron.spi.NeutronPort)
464      */
465     @Override
466     public void neutronPortUpdated(NeutronPort port) {
467         LOG.trace("neutronPortUpdated - {}", port);
468         if (isRouterInterfacePort(port)) {
469             LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
470                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
471             return;
472         }
473         if (isRouterGatewayPort(port)) {
474             LOG.trace("Port is router gateway - {}", port.getID());
475             return;
476         }
477         if (isFloatingIpPort(port)) {
478             LOG.trace("Port is floating ip - {}", port.getID());
479             return;
480         }
481         if (Strings.isNullOrEmpty(port.getTenantID())) {
482             LOG.trace("REMOVE ME: Tenant is null - {}", port.getID());
483             return;
484         }
485
486         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
487         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
488         MacAddress macAddress = new MacAddress(port.getMacAddress());
489         L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
490         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
491         boolean isFwCtxValid = validateForwardingCtx(fwCtx);
492         if (!isFwCtxValid) {
493             rTx.close();
494             return;
495         }
496
497         Optional<Endpoint> potentionalEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
498                 IidFactory.endpointIid(fwCtx.getL2BridgeDomain().getId(), macAddress), rTx);
499         if (!potentionalEp.isPresent()) {
500             LOG.warn("Illegal state - endpoint {} does not exist.", new EndpointKey(fwCtx.getL2BridgeDomain().getId(),
501                     macAddress));
502             rTx.close();
503             return;
504         }
505
506         Endpoint ep = potentionalEp.get();
507         if (isEpIpDifferentThanPortFixedIp(ep, port) || isEpgDifferentThanSecGrp(ep, port)) {
508             UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(ep);
509             RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
510             try {
511                 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
512                 if (!rpcResult.isSuccessful()) {
513                     LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
514                     rTx.close();
515                     return;
516                 }
517                 rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
518                 if (!rpcResult.isSuccessful()) {
519                     LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
520                     rTx.close();
521                     return;
522                 }
523             } catch (InterruptedException | ExecutionException e) {
524                 LOG.error("addPort - RPC invocation failed.", e);
525                 rTx.close();
526                 return;
527             }
528         }
529         rTx.close();
530     }
531
532     private boolean isEpIpDifferentThanPortFixedIp(Endpoint ep, NeutronPort port) {
533         List<L3Address> l3Addresses = ep.getL3Address();
534         List<Neutron_IPs> fixedIPs = port.getFixedIPs();
535         if ((l3Addresses == null || l3Addresses.isEmpty()) && (fixedIPs == null || fixedIPs.isEmpty())) {
536             return false;
537         }
538         if (l3Addresses != null && !l3Addresses.isEmpty() && fixedIPs != null && !fixedIPs.isEmpty()) {
539             if (fixedIPs.get(0).getIpAddress().equals(Utils.getStringIpAddress(l3Addresses.get(0).getIpAddress()))) {
540                 return false;
541             }
542         }
543         return true;
544     }
545
546     private boolean isEpgDifferentThanSecGrp(Endpoint ep, NeutronPort port) {
547         List<EndpointGroupId> epgIds = ep.getEndpointGroups();
548         List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
549         if ((epgIds == null || epgIds.isEmpty()) && (secGroups == null || secGroups.isEmpty())) {
550             return false;
551         }
552         if (epgIds != null && !epgIds.isEmpty() && secGroups != null && !secGroups.isEmpty()) {
553             if (epgIds.size() != secGroups.size()) {
554                 return true;
555             }
556             Collection<EndpointGroupId> epgIdsFromSecGroups = Collections2.transform(secGroups,
557                     new Function<NeutronSecurityGroup, EndpointGroupId>() {
558
559                         @Override
560                         public EndpointGroupId apply(NeutronSecurityGroup input) {
561                             return new EndpointGroupId(input.getSecurityGroupUUID());
562                         }
563                     });
564             // order independent equals
565             Set<EndpointGroupId> one = new HashSet<>(epgIds);
566             Set<EndpointGroupId> two = new HashSet<>(epgIdsFromSecGroups);
567             if (one.equals(two)) {
568                 return false;
569             }
570         }
571         return true;
572     }
573
574     /**
575      * @see org.opendaylight.neutron.spi.INeutronPortAware#canDeletePort(org.opendaylight.neutron.spi.NeutronPort)
576      */
577     @Override
578     public int canDeletePort(NeutronPort port) {
579         LOG.trace("canDeletePort - {}", port);
580         // nothing to consider
581         return StatusCode.OK;
582     }
583
584     /**
585      * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortDeleted(org.opendaylight.neutron.spi.NeutronPort)
586      */
587     @Override
588     public void neutronPortDeleted(NeutronPort port) {
589         LOG.trace("neutronPortDeleted - {}", port);
590         if (isRouterInterfacePort(port)) {
591             LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
592                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
593             return;
594         }
595         if (isRouterGatewayPort(port)) {
596             LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
597                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
598             return;
599         }
600         if (isFloatingIpPort(port)) {
601             LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
602             floatingIpPortByDeviceId.remove(port.getDeviceID());
603         }
604         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
605         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
606         L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
607         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
608         boolean isFwCtxValid = validateForwardingCtx(fwCtx);
609         if (!isFwCtxValid) {
610             rwTx.cancel();
611             return;
612         }
613
614         EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
615         deleteNeutronGbpMapping(port, epKey, rwTx);
616         UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
617         try {
618             RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
619             if (!rpcResult.isSuccessful()) {
620                 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
621             }
622         } catch (InterruptedException | ExecutionException e) {
623             LOG.error("addPort - RPC invocation failed.", e);
624             rwTx.cancel();
625         }
626     }
627
628     private static void deleteNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
629         UniqueId portId = new UniqueId(port.getID());
630         if (isRouterInterfacePort(port)) {
631             LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
632             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
633                     NeutronGbpIidFactory.endpointByRouterInterfacePortIid(portId), rwTx);
634             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
635                     NeutronGbpIidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
636         } else if (isRouterGatewayPort(port)) {
637             LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
638             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
639                     NeutronGbpIidFactory.endpointByRouterGatewayPortIid(portId), rwTx);
640             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
641                     NeutronGbpIidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
642         } else if (isFloatingIpPort(port)) {
643             LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
644             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
645                     NeutronGbpIidFactory.endpointByFloatingIpPortIid(portId), rwTx);
646             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
647                     NeutronGbpIidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
648         } else {
649             LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
650                     port.getDeviceOwner(), epKey);
651             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), rwTx);
652             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
653                     NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
654         }
655     }
656
657     private static RegisterL3PrefixEndpointInput createRegisterL3PrefixEndpointInput(EndpointL3PrefixKey key, List<EndpointL3Key> endpointL3Keys, TenantId tenantId) {
658         List<EndpointGroupId> epgIds = new ArrayList<>();
659         // each EP has to be in EPG ANY, except dhcp and router
660         epgIds.add(MappingUtils.EPG_ANY_ID);
661
662         List<EndpointL3Gateways> l3Gateways = new ArrayList<EndpointL3Gateways>();
663         for (EndpointL3Key epL3Key : endpointL3Keys) {
664             EndpointL3Gateways l3Gateway = new EndpointL3GatewaysBuilder().setIpAddress(epL3Key.getIpAddress())
665                 .setL3Context(epL3Key.getL3Context())
666                 .build();
667             l3Gateways.add(l3Gateway);
668         }
669         RegisterL3PrefixEndpointInputBuilder inputBuilder = new RegisterL3PrefixEndpointInputBuilder()
670                                                 .setL3Context(key.getL3Context())
671                                                 .setIpPrefix(key.getIpPrefix())
672                                                 .setEndpointGroups(epgIds)
673                                                 .setTenant(tenantId)
674                                                 .setEndpointL3Gateways(l3Gateways)
675                                                 .setTimestamp(System.currentTimeMillis());
676         return inputBuilder.build();
677     }
678
679     private static EndpointL3 createL3Endpoint(TenantId tenantId, EndpointL3Key epL3Key,
680             List<EndpointGroupId> epgIds, NetworkDomainId containment) {
681
682         EndpointL3Builder epL3Builder = new EndpointL3Builder()
683         .setTenant(tenantId)
684         .setNetworkContainment(containment)
685         .setIpAddress(epL3Key.getIpAddress())
686         .setL3Context(epL3Key.getL3Context())
687         .setEndpointGroups(epgIds)
688         .setTimestamp(System.currentTimeMillis());
689
690         return epL3Builder.build();
691     }
692
693     private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
694         List<EndpointGroupId> epgIds = new ArrayList<>();
695         // each EP has to be in EPG ANY, except dhcp and router
696         if (isDhcpPort(port)) {
697             epgIds.add(MappingUtils.EPG_DHCP_ID);
698         } else if (!containsSecRuleWithRemoteSecGroup(port.getSecurityGroups())) {
699             epgIds.add(MappingUtils.EPG_ANY_ID);
700         }
701
702         List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
703         if ((securityGroups == null || securityGroups.isEmpty())) {
704             if (isFloatingIpPort(port)) {
705                 epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
706             } else if (!isDhcpPort(port)) {
707                 LOG.warn(
708                         "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
709                         port.getPortUUID());
710             }
711         } else {
712             for (NeutronSecurityGroup secGrp : securityGroups) {
713                 epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID()));
714             }
715         }
716         LocationType locationType = LocationType.Internal;
717         if(isRouterGatewayPort(port)) {
718             locationType = LocationType.External;
719         }
720         RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context(
721                 fwCtx.getL2BridgeDomain().getId())
722             .setMacAddress(new MacAddress(port.getMacAddress()))
723             .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID())))
724             .setEndpointGroups(epgIds)
725             .addAugmentation(OfOverlayContextInput.class,
726                     new OfOverlayContextInputBuilder()
727                         .setPortName(createTapPortName(port))
728                         .setLocationType(locationType)
729                     .build())
730             .setTimestamp(System.currentTimeMillis());
731         List<Neutron_IPs> fixedIPs = port.getFixedIPs();
732         // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer
733         // will support l3-endpoints. Then we will register L2 and L3 endpoints separately.
734         Neutron_IPs firstIp = MappingUtils.getFirstIp(fixedIPs);
735         if (firstIp != null) {
736             inputBuilder.setNetworkContainment(new SubnetId(firstIp.getSubnetUUID()));
737             L3Address l3Address = new L3AddressBuilder().setIpAddress(Utils.createIpAddress(firstIp.getIpAddress()))
738                 .setL3Context(fwCtx.getL3Context().getId())
739                 .build();
740             inputBuilder.setL3Address(ImmutableList.of(l3Address));
741         }
742         if (!Strings.isNullOrEmpty(port.getName())) {
743
744         }
745         return inputBuilder.build();
746     }
747
748     private static boolean containsSecRuleWithRemoteSecGroup(List<NeutronSecurityGroup> secGroups) {
749         if (secGroups == null) {
750             return false;
751         }
752         for (NeutronSecurityGroup secGroup : secGroups) {
753             boolean containsSecRuleWithRemoteSecGroup = containsSecRuleWithRemoteSecGroup(secGroup);
754             if (containsSecRuleWithRemoteSecGroup) {
755                 return true;
756             }
757         }
758         return false;
759     }
760
761     private static boolean containsSecRuleWithRemoteSecGroup(NeutronSecurityGroup secGroup) {
762         List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
763         if (secRules == null) {
764             return false;
765         }
766         for (NeutronSecurityRule secRule : secRules) {
767             if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
768                 return true;
769             }
770         }
771         return false;
772     }
773
774     private static Name createTapPortName(NeutronPort port) {
775         return new Name("tap" + port.getID().substring(0, 11));
776     }
777
778     private static boolean isDhcpPort(NeutronPort port) {
779         return DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
780     }
781
782     private static boolean isRouterInterfacePort(NeutronPort port) {
783         return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner());
784     }
785
786     private static boolean isRouterGatewayPort(NeutronPort port) {
787         return DEVICE_OWNER_ROUTER_GATEWAY.equals(port.getDeviceOwner());
788     }
789
790     private static boolean isFloatingIpPort(NeutronPort port) {
791         return DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner());
792     }
793
794     private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) {
795         UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
796         L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build();
797         inputBuilder.setL2(ImmutableList.of(l2Ep));
798         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
799         // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
800         // be registered separately.
801         if (ep.getL3Address() != null && !ep.getL3Address().isEmpty()) {
802             List<L3> l3Eps = new ArrayList<>();
803             for (L3Address ip : ep.getL3Address()) {
804                 l3Eps.add(new L3Builder().setL3Context(ip.getL3Context()).setIpAddress(ip.getIpAddress()).build());
805             }
806             inputBuilder.setL3(l3Eps);
807         }
808         return inputBuilder.build();
809     }
810
811     private UnregisterEndpointInput createUnregisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
812         UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
813         L2 l2Ep = new L2Builder().setL2Context(fwCtx.getL2BridgeDomain().getId())
814             .setMacAddress(new MacAddress(port.getMacAddress()))
815             .build();
816         inputBuilder.setL2(ImmutableList.of(l2Ep));
817         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
818         // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
819         // be registered separately.
820         if (port.getFixedIPs() != null && !port.getFixedIPs().isEmpty()) {
821             inputBuilder.setL3(createL3s(port.getFixedIPs(), fwCtx.getL3Context().getId()));
822         }
823         return inputBuilder.build();
824     }
825
826     private List<L3> createL3s(List<Neutron_IPs> neutronIps, L3ContextId l3ContextId) {
827         List<L3> l3s = new ArrayList<>();
828         for (Neutron_IPs fixedIp : neutronIps) {
829             String ip = fixedIp.getIpAddress();
830             L3 l3 = new L3Builder().setIpAddress(Utils.createIpAddress(ip)).setL3Context(l3ContextId).build();
831             l3s.add(l3);
832         }
833         return l3s;
834     }
835
836     public static UniqueId getFloatingIpPortIdByDeviceId(String deviceId) {
837         return floatingIpPortByDeviceId.get(deviceId);
838     }
839
840 }