Merge "Removed calling of NeutronRouterAware API from NeutronPortAware"
[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.HashSet;
15 import java.util.List;
16 import java.util.Set;
17 import java.util.concurrent.ExecutionException;
18
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
21 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
30 import org.opendaylight.neutron.spi.INeutronPortAware;
31 import org.opendaylight.neutron.spi.NeutronPort;
32 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
33 import org.opendaylight.neutron.spi.NeutronSecurityRule;
34 import org.opendaylight.neutron.spi.Neutron_IPs;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
60 import org.opendaylight.yangtools.yang.common.RpcResult;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 import com.google.common.base.Function;
65 import com.google.common.base.Optional;
66 import com.google.common.base.Strings;
67 import com.google.common.collect.Collections2;
68 import com.google.common.collect.ImmutableList;
69
70 public class NeutronPortAware implements INeutronPortAware {
71
72     public static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
73     private static final String DEVICE_OWNER_DHCP = "network:dhcp";
74     private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
75     private static final int DHCP_CLIENT_PORT = 68;
76     private static final int DHCP_SERVER_PORT = 67;
77     private final DataBroker dataProvider;
78     private final EndpointService epService;
79
80     public NeutronPortAware(DataBroker dataProvider, EndpointService epService) {
81         this.dataProvider = checkNotNull(dataProvider);
82         this.epService = checkNotNull(epService);
83     }
84
85     /**
86      * @see org.opendaylight.neutron.spi.INeutronPortAware#canCreatePort(org.opendaylight.neutron.spi.NeutronPort)
87      */
88     @Override
89     public int canCreatePort(NeutronPort port) {
90         LOG.trace("canCreatePort - {}", port);
91         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
92         List<Neutron_IPs> fixedIPs = port.getFixedIPs();
93         if (fixedIPs != null && fixedIPs.size() > 1) {
94             LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
95             return StatusCode.BAD_REQUEST;
96         }
97         return StatusCode.OK;
98     }
99
100     /**
101      * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortCreated(org.opendaylight.neutron.spi.NeutronPort)
102      */
103     @Override
104     public void neutronPortCreated(NeutronPort port) {
105         LOG.trace("neutronPortCreated - {}", port);
106         if (isRouterInterfacePort(port)) {
107             LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
108                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
109             return;
110         }
111         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
112         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
113         if (isDhcpPort(port)) {
114             LOG.trace("Port is DHCP port.");
115             List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, null, rwTx);
116             if (dhcpSecRules == null) {
117                 rwTx.cancel();
118                 return;
119             }
120
121             for (NeutronSecurityRule dhcpSecRule : dhcpSecRules) {
122                 boolean isDhcpSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(dhcpSecRule, rwTx);
123                 if (!isDhcpSecRuleAdded) {
124                     rwTx.cancel();
125                     return;
126                 }
127             }
128         } else {
129             List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
130             if (secGroups != null) {
131                 for (NeutronSecurityGroup secGroup : secGroups) {
132                     EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
133                     Optional<EndpointGroup> potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
134                             IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
135                     if (!potentialEpg.isPresent()) {
136                         boolean isSecGroupCreated = NeutronSecurityGroupAware.addNeutronSecurityGroup(secGroup, rwTx);
137                         if (!isSecGroupCreated) {
138                             rwTx.cancel();
139                             return;
140                         }
141                         if (containsSecRuleWithRemoteSecGroup(secGroup)) {
142                             List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, epgId, rwTx);
143                             if (dhcpSecRules == null) {
144                                 rwTx.cancel();
145                                 return;
146                             }
147                             List<NeutronSecurityRule> routerSecRules = NeutronRouterAware.createRouterSecRules(port, epgId, rwTx);
148                             if (routerSecRules == null) {
149                                 rwTx.cancel();
150                                 return;
151                             }
152                         }
153                     } else {
154                         List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
155                         if (secRules != null) {
156                             for (NeutronSecurityRule secRule : secRules) {
157                                 NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx);
158                             }
159                         }
160                     }
161                 }
162             }
163         }
164
165         boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService);
166         if (!isNeutronPortCreated) {
167             rwTx.cancel();
168             return;
169         }
170
171         DataStoreHelper.submitToDs(rwTx);
172     }
173
174     public static boolean addNeutronPort(NeutronPort port, ReadWriteTransaction rwTx, EndpointService epService) {
175         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
176         L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
177         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
178         boolean isFwCtxValid = validateForwardingCtx(fwCtx);
179         if (!isFwCtxValid) {
180             return false;
181         }
182
183         try {
184             RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
185             RpcResult<Void> rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
186             if (!rpcResult.isSuccessful()) {
187                 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
188                 return false;
189             }
190         } catch (InterruptedException | ExecutionException e) {
191             LOG.error("addPort - RPC invocation failed.", e);
192             return false;
193         }
194         return true;
195     }
196
197     private static boolean validateForwardingCtx(ForwardingCtx fwCtx) {
198         if (fwCtx.getL2FloodDomain() == null) {
199             LOG.warn("Illegal state - l2-flood-domain does not exist.");
200             return false;
201         }
202         if (fwCtx.getL2BridgeDomain() == null) {
203             LOG.warn("Illegal state - l2-bridge-domain does not exist.");
204             return false;
205         }
206         if (fwCtx.getL3Context() == null) {
207             LOG.warn("Illegal state - l3-context does not exist.");
208             return false;
209         }
210         return true;
211     }
212
213     private List<NeutronSecurityRule> createDhcpSecRules(NeutronPort port, EndpointGroupId consumerEpgId, ReadTransaction rTx) {
214         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
215         Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
216         if (firstIp == null) {
217             LOG.warn("Illegal state - DHCP port does not have an IP address.");
218             return null;
219         }
220         SubnetId dhcpSubnetId = new SubnetId(firstIp.getSubnetUUID());
221         Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
222                 IidFactory.subnetIid(tenantId, dhcpSubnetId), rTx);
223         if (!potentialSubnet.isPresent()) {
224             LOG.warn("Illegal state - Subnet {} where is DHCP port does not exist.", dhcpSubnetId.getValue());
225             return null;
226         }
227         IpPrefix ipSubnet = potentialSubnet.get().getIpPrefix();
228         NeutronSecurityRule dhcpRuleEgress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, true);
229         NeutronSecurityRule dhcpRuleIngress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, false);
230         return ImmutableList.of(dhcpRuleEgress, dhcpRuleIngress);
231     }
232
233     private NeutronSecurityRule createDhcpSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId,
234             boolean isEgress) {
235         NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
236         dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
237         dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
238         dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
239         if (consumerEpgId != null) {
240             dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
241         }
242         if (isEgress) {
243             dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid);
244             dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
245             dhcpSecRule.setSecurityRulePortMin(DHCP_CLIENT_PORT);
246             dhcpSecRule.setSecurityRulePortMax(DHCP_CLIENT_PORT);
247         } else {
248             dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid);
249             dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
250             dhcpSecRule.setSecurityRulePortMin(DHCP_SERVER_PORT);
251             dhcpSecRule.setSecurityRulePortMax(DHCP_SERVER_PORT);
252         }
253         dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
254         if (ipSubnet.getIpv4Prefix() != null) {
255             dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
256         } else {
257             dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
258         }
259         return dhcpSecRule;
260     }
261
262     /**
263      * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort,
264      *      org.opendaylight.neutron.spi.NeutronPort)
265      */
266     @Override
267     public int canUpdatePort(NeutronPort delta, NeutronPort original) {
268         LOG.trace("canUpdatePort - delta: {} original: {}", delta, original);
269         if (delta.getFixedIPs() == null || delta.getFixedIPs().isEmpty()) {
270             return StatusCode.OK;
271         }
272         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
273         List<Neutron_IPs> fixedIPs = delta.getFixedIPs();
274         if (fixedIPs != null && fixedIPs.size() > 1) {
275             LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
276             return StatusCode.BAD_REQUEST;
277         }
278         return StatusCode.OK;
279     }
280
281     /**
282      * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortUpdated(org.opendaylight.neutron.spi.NeutronPort)
283      */
284     @Override
285     public void neutronPortUpdated(NeutronPort port) {
286         LOG.trace("neutronPortUpdated - {}", port);
287         if (isRouterInterfacePort(port)) {
288             LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
289                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
290             return;
291         }
292         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
293         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
294         MacAddress macAddress = new MacAddress(port.getMacAddress());
295         L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
296         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
297         boolean isFwCtxValid = validateForwardingCtx(fwCtx);
298         if (!isFwCtxValid) {
299             rTx.close();
300             return;
301         }
302
303         Optional<Endpoint> potentionalEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
304                 IidFactory.endpointIid(fwCtx.getL2BridgeDomain().getId(), macAddress), rTx);
305         if (!potentionalEp.isPresent()) {
306             LOG.warn("Illegal state - endpoint {} does not exist.", new EndpointKey(fwCtx.getL2BridgeDomain().getId(),
307                     macAddress));
308             rTx.close();
309             return;
310         }
311
312         Endpoint ep = potentionalEp.get();
313         if (isEpIpDifferentThanPortFixedIp(ep, port) || isEpgDifferentThanSecGrp(ep, port)) {
314             UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(ep);
315             RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
316             try {
317                 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
318                 if (!rpcResult.isSuccessful()) {
319                     LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
320                     rTx.close();
321                     return;
322                 }
323                 rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
324                 if (!rpcResult.isSuccessful()) {
325                     LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
326                     rTx.close();
327                     return;
328                 }
329             } catch (InterruptedException | ExecutionException e) {
330                 LOG.error("addPort - RPC invocation failed.", e);
331                 rTx.close();
332                 return;
333             }
334         }
335         rTx.close();
336     }
337
338     private boolean isEpIpDifferentThanPortFixedIp(Endpoint ep, NeutronPort port) {
339         List<L3Address> l3Addresses = ep.getL3Address();
340         List<Neutron_IPs> fixedIPs = port.getFixedIPs();
341         if ((l3Addresses == null || l3Addresses.isEmpty()) && (fixedIPs == null || fixedIPs.isEmpty())) {
342             return false;
343         }
344         if (l3Addresses != null && !l3Addresses.isEmpty() && fixedIPs != null && !fixedIPs.isEmpty()) {
345             if (fixedIPs.get(0).getIpAddress().equals(Utils.getStringIpAddress(l3Addresses.get(0).getIpAddress()))) {
346                 return false;
347             }
348         }
349         return true;
350     }
351
352     private boolean isEpgDifferentThanSecGrp(Endpoint ep, NeutronPort port) {
353         List<EndpointGroupId> epgIds = ep.getEndpointGroups();
354         List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
355         if ((epgIds == null || epgIds.isEmpty()) && (secGroups == null || secGroups.isEmpty())) {
356             return false;
357         }
358         if (epgIds != null && !epgIds.isEmpty() && secGroups != null && !secGroups.isEmpty()) {
359             if (epgIds.size() != secGroups.size()) {
360                 return true;
361             }
362             Collection<EndpointGroupId> epgIdsFromSecGroups = Collections2.transform(secGroups,
363                     new Function<NeutronSecurityGroup, EndpointGroupId>() {
364
365                         @Override
366                         public EndpointGroupId apply(NeutronSecurityGroup input) {
367                             return new EndpointGroupId(input.getSecurityGroupUUID());
368                         }
369                     });
370             // order independent equals
371             Set<EndpointGroupId> one = new HashSet<>(epgIds);
372             Set<EndpointGroupId> two = new HashSet<>(epgIdsFromSecGroups);
373             if (one.equals(two)) {
374                 return false;
375             }
376         }
377         return true;
378     }
379
380     /**
381      * @see org.opendaylight.neutron.spi.INeutronPortAware#canDeletePort(org.opendaylight.neutron.spi.NeutronPort)
382      */
383     @Override
384     public int canDeletePort(NeutronPort port) {
385         LOG.trace("canDeletePort - {}", port);
386         // nothing to consider
387         return StatusCode.OK;
388     }
389
390     /**
391      * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortDeleted(org.opendaylight.neutron.spi.NeutronPort)
392      */
393     @Override
394     public void neutronPortDeleted(NeutronPort port) {
395         LOG.trace("neutronPortDeleted - {}", port);
396         if (isRouterInterfacePort(port)) {
397             LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
398                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
399             return;
400         }
401         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
402         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
403         L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
404         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
405         boolean isFwCtxValid = validateForwardingCtx(fwCtx);
406         if (!isFwCtxValid) {
407             rTx.close();
408             return;
409         }
410
411         UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
412         try {
413             RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
414             if (!rpcResult.isSuccessful()) {
415                 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
416             }
417         } catch (InterruptedException | ExecutionException e) {
418             LOG.error("addPort - RPC invocation failed.", e);
419         } finally {
420             rTx.close();
421         }
422     }
423
424     private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
425         List<EndpointGroupId> epgIds = new ArrayList<>();
426         // each EP has to be in EPG ANY, except dhcp and router
427         if (isDhcpPort(port)) {
428             epgIds.add(MappingUtils.EPG_DHCP_ID);
429         } else if (!containsSecRuleWithRemoteSecGroup(port.getSecurityGroups())) {
430             epgIds.add(MappingUtils.EPG_ANY_ID);
431         }
432
433         List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
434         if ((securityGroups == null || securityGroups.isEmpty())) {
435             if (!isDhcpPort(port)) {
436                 LOG.warn(
437                         "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
438                         port.getPortUUID());
439             }
440         } else {
441             for (NeutronSecurityGroup secGrp : securityGroups) {
442                 epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID()));
443             }
444         }
445         RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context(
446                 fwCtx.getL2BridgeDomain().getId())
447             .setMacAddress(new MacAddress(port.getMacAddress()))
448             .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID())))
449             .setEndpointGroups(epgIds)
450             .addAugmentation(OfOverlayContextInput.class,
451                     new OfOverlayContextInputBuilder().setPortName(createTapPortName(port)).build())
452             .setTimestamp(System.currentTimeMillis());
453         List<Neutron_IPs> fixedIPs = port.getFixedIPs();
454         // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer
455         // will support l3-endpoints. Then we will register L2 and L3 endpoints separately.
456         Neutron_IPs firstIp = MappingUtils.getFirstIp(fixedIPs);
457         if (firstIp != null) {
458             inputBuilder.setNetworkContainment(new SubnetId(firstIp.getSubnetUUID()));
459             L3Address l3Address = new L3AddressBuilder().setIpAddress(Utils.createIpAddress(firstIp.getIpAddress()))
460                 .setL3Context(fwCtx.getL3Context().getId())
461                 .build();
462             inputBuilder.setL3Address(ImmutableList.of(l3Address));
463         }
464         if (!Strings.isNullOrEmpty(port.getName())) {
465
466         }
467         return inputBuilder.build();
468     }
469
470     private static boolean containsSecRuleWithRemoteSecGroup(List<NeutronSecurityGroup> secGroups) {
471         if (secGroups == null) {
472             return false;
473         }
474         for (NeutronSecurityGroup secGroup : secGroups) {
475             boolean containsSecRuleWithRemoteSecGroup = containsSecRuleWithRemoteSecGroup(secGroup);
476             if (containsSecRuleWithRemoteSecGroup) {
477                 return true;
478             }
479         }
480         return false;
481     }
482
483     private static boolean containsSecRuleWithRemoteSecGroup(NeutronSecurityGroup secGroup) {
484         List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
485         if (secRules == null) {
486             return false;
487         }
488         for (NeutronSecurityRule secRule : secRules) {
489             if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
490                 return true;
491             }
492         }
493         return false;
494     }
495
496     private static Name createTapPortName(NeutronPort port) {
497         return new Name("tap" + port.getID().substring(0, 11));
498     }
499
500     private static boolean isDhcpPort(NeutronPort port) {
501         return DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
502     }
503
504     private static boolean isRouterInterfacePort(NeutronPort port) {
505         return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner());
506     }
507
508     private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) {
509         UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
510         L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build();
511         inputBuilder.setL2(ImmutableList.of(l2Ep));
512         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
513         // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
514         // be registered separately.
515         if (ep.getL3Address() != null && !ep.getL3Address().isEmpty()) {
516             List<L3> l3Eps = new ArrayList<>();
517             for (L3Address ip : ep.getL3Address()) {
518                 l3Eps.add(new L3Builder().setL3Context(ip.getL3Context()).setIpAddress(ip.getIpAddress()).build());
519             }
520             inputBuilder.setL3(l3Eps);
521         }
522         return inputBuilder.build();
523     }
524
525     private UnregisterEndpointInput createUnregisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
526         UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
527         L2 l2Ep = new L2Builder().setL2Context(fwCtx.getL2BridgeDomain().getId())
528             .setMacAddress(new MacAddress(port.getMacAddress()))
529             .build();
530         inputBuilder.setL2(ImmutableList.of(l2Ep));
531         // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
532         // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
533         // be registered separately.
534         if (port.getFixedIPs() != null && !port.getFixedIPs().isEmpty()) {
535             inputBuilder.setL3(createL3s(port.getFixedIPs(), fwCtx.getL3Context().getId()));
536         }
537         return inputBuilder.build();
538     }
539
540     private List<L3> createL3s(List<Neutron_IPs> neutronIps, L3ContextId l3ContextId) {
541         List<L3> l3s = new ArrayList<>();
542         for (Neutron_IPs fixedIp : neutronIps) {
543             String ip = fixedIp.getIpAddress();
544             L3 l3 = new L3Builder().setIpAddress(Utils.createIpAddress(ip)).setL3Context(l3ContextId).build();
545             l3s.add(l3);
546         }
547         return l3s;
548     }
549
550 }