2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
10 import static com.google.common.base.Preconditions.checkNotNull;
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;
19 import java.util.concurrent.ExecutionException;
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.SubnetId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.floating.ip.ports.EndpointByFloatingIpPort;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router._interface.ports.EndpointByRouterInterfacePort;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router.gateway.ports.EndpointByRouterGatewayPort;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.floating.ip.ports.by.endpoints.FloatingIpPortByEndpoint;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router._interface.ports.by.endpoints.RouterInterfacePortByEndpoint;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router.gateway.ports.by.endpoints.RouterGatewayPortByEndpoint;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
80 import org.opendaylight.yangtools.yang.common.RpcResult;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
84 import com.google.common.base.Function;
85 import com.google.common.base.Optional;
86 import com.google.common.base.Strings;
87 import com.google.common.collect.Collections2;
88 import com.google.common.collect.ImmutableList;
90 public class NeutronPortAware implements INeutronPortAware {
92 public static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
93 private static final String DEVICE_OWNER_DHCP = "network:dhcp";
94 private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
95 private static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway";
96 private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
97 private static final int DHCP_SERVER_PORT = 67;
98 private static final int DNS_SERVER_PORT = 53;
99 private final DataBroker dataProvider;
100 private final EndpointService epService;
101 private final static Map<String, UniqueId> floatingIpPortByDeviceId = new HashMap<>();
103 public NeutronPortAware(DataBroker dataProvider, EndpointService epService) {
104 this.dataProvider = checkNotNull(dataProvider);
105 this.epService = checkNotNull(epService);
109 * @see org.opendaylight.neutron.spi.INeutronPortAware#canCreatePort(org.opendaylight.neutron.spi.NeutronPort)
112 public int canCreatePort(NeutronPort port) {
113 LOG.trace("canCreatePort - {}", port);
114 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
115 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
116 if (fixedIPs != null && fixedIPs.size() > 1) {
117 LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
118 return StatusCode.BAD_REQUEST;
120 return StatusCode.OK;
124 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortCreated(org.opendaylight.neutron.spi.NeutronPort)
127 public void neutronPortCreated(NeutronPort port) {
128 LOG.trace("neutronPortCreated - {}", port);
129 if (isRouterInterfacePort(port)) {
130 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
131 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
134 if (isRouterGatewayPort(port)) {
135 LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
136 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
139 if (isFloatingIpPort(port)) {
140 LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
141 floatingIpPortByDeviceId.put(port.getDeviceID(), new UniqueId(port.getID()));
144 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
145 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
146 if (isDhcpPort(port)) {
147 LOG.trace("Port is DHCP port. - {}", port.getID());
148 List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, null, rwTx);
149 if (dhcpSecRules == null) {
154 for (NeutronSecurityRule dhcpSecRule : dhcpSecRules) {
155 boolean isDhcpSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(dhcpSecRule, rwTx);
156 if (!isDhcpSecRuleAdded) {
162 List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
163 if (secGroups != null) {
164 for (NeutronSecurityGroup secGroup : secGroups) {
165 EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
166 Optional<EndpointGroup> potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
167 IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
168 if (!potentialEpg.isPresent()) {
169 boolean isSecGroupCreated = NeutronSecurityGroupAware.addNeutronSecurityGroup(secGroup, rwTx);
170 if (!isSecGroupCreated) {
174 if (containsSecRuleWithRemoteSecGroup(secGroup)) {
175 List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, epgId, rwTx);
176 if (dhcpSecRules == null) {
180 List<NeutronSecurityRule> routerSecRules = NeutronRouterAware.createRouterSecRules(port, epgId, rwTx);
181 if (routerSecRules == null) {
187 List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
188 if (secRules != null) {
189 for (NeutronSecurityRule secRule : secRules) {
190 NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx);
197 boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService);
198 if (!isNeutronPortCreated) {
203 DataStoreHelper.submitToDs(rwTx);
206 public static boolean addNeutronPort(NeutronPort port, ReadWriteTransaction rwTx, EndpointService epService) {
207 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
208 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
209 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
210 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
214 EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
215 addNeutronGbpMapping(port, epKey, rwTx);
218 RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
220 RpcResult<Void> rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
221 if (!rpcResult.isSuccessful()) {
222 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
225 } catch (InterruptedException | ExecutionException e) {
226 LOG.error("addPort - RPC invocation failed.", e);
232 private static void addNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
233 UniqueId portId = new UniqueId(port.getID());
234 if (isRouterInterfacePort(port)) {
235 LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
236 EndpointByRouterInterfacePort endpointByPort = MappingFactory.createEndpointByRouterInterfacePort(epKey,
238 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterInterfacePortIid(portId),
239 endpointByPort, true);
240 RouterInterfacePortByEndpoint portByEndpoint = MappingFactory.createRouterInterfacePortByEndpoint(portId,
242 rwTx.put(LogicalDatastoreType.OPERATIONAL,
243 NeutronGbpIidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
244 portByEndpoint, true);
245 } else if (isRouterGatewayPort(port)) {
246 LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
247 EndpointByRouterGatewayPort endpointByPort = MappingFactory.createEndpointByRouterGatewayPort(epKey, portId);
248 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterGatewayPortIid(portId),
249 endpointByPort, true);
250 RouterGatewayPortByEndpoint portByEndpoint = MappingFactory.createRouterGatewayPortByEndpoint(portId, epKey);
251 rwTx.put(LogicalDatastoreType.OPERATIONAL,
252 NeutronGbpIidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
253 portByEndpoint, true);
254 } else if (isFloatingIpPort(port)) {
255 LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
256 EndpointByFloatingIpPort endpointByPort = MappingFactory.createEndpointByFloatingIpPort(epKey, portId);
257 rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByFloatingIpPortIid(portId),
258 endpointByPort, true);
259 FloatingIpPortByEndpoint portByEndpoint = MappingFactory.createFloatingIpPortByEndpoint(portId, epKey);
260 rwTx.put(LogicalDatastoreType.OPERATIONAL,
261 IidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
262 portByEndpoint, true);
264 LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
265 port.getDeviceOwner(), epKey);
266 EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
267 rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort, true);
268 PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
269 rwTx.put(LogicalDatastoreType.OPERATIONAL,
270 NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint, true);
274 public static boolean addL3PrefixEndpoint(L3ContextId l3ContextId, IpPrefix ipPrefix, IpAddress ipAddress, TenantId tenantId,
275 ReadWriteTransaction rwTx, EndpointService epService) {
277 EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey( ipPrefix, l3ContextId);
279 EndpointL3Key epL3Key = null;
280 List<EndpointL3Key> l3Gateways = new ArrayList<>();
281 if (ipAddress != null) {
282 epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
283 l3Gateways.add(epL3Key);
288 RegisterL3PrefixEndpointInput registerL3PrefixEpRpcInput = createRegisterL3PrefixEndpointInput(epL3PrefixKey, l3Gateways,tenantId);
290 RpcResult<Void> rpcResult = epService.registerL3PrefixEndpoint(registerL3PrefixEpRpcInput).get();
291 if (!rpcResult.isSuccessful()) {
292 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerL3PrefixEpRpcInput);
295 } catch (InterruptedException | ExecutionException e) {
296 LOG.error("addPort - RPC invocation failed.", e);
303 private static boolean validateForwardingCtx(ForwardingCtx fwCtx) {
304 if (fwCtx.getL2FloodDomain() == null) {
305 LOG.warn("Illegal state - l2-flood-domain does not exist.");
308 if (fwCtx.getL2BridgeDomain() == null) {
309 LOG.warn("Illegal state - l2-bridge-domain does not exist.");
312 if (fwCtx.getL3Context() == null) {
313 LOG.warn("Illegal state - l3-context does not exist.");
319 private List<NeutronSecurityRule> createDhcpSecRules(NeutronPort port, EndpointGroupId consumerEpgId, ReadTransaction rTx) {
320 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
321 Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
322 if (firstIp == null) {
323 LOG.warn("Illegal state - DHCP port does not have an IP address.");
326 SubnetId dhcpSubnetId = new SubnetId(firstIp.getSubnetUUID());
327 Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
328 IidFactory.subnetIid(tenantId, dhcpSubnetId), rTx);
329 if (!potentialSubnet.isPresent()) {
330 LOG.warn("Illegal state - Subnet {} where is DHCP port does not exist.", dhcpSubnetId.getValue());
333 IpPrefix ipSubnet = potentialSubnet.get().getIpPrefix();
334 List<NeutronSecurityRule> rules = new ArrayList<>();
335 rules.add(createDhcpIngressSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId));
336 rules.add(createDnsSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId));
337 rules.add(createUdpEgressSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId));
338 rules.add(createIcmpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, true));
339 rules.add(createIcmpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, false));
343 private NeutronSecurityRule createDhcpIngressSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId) {
344 NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
345 dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
346 dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
347 dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
348 if (consumerEpgId != null) {
349 dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
351 dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "_dhcp__" + ruleUuid);
352 dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
353 dhcpSecRule.setSecurityRulePortMin(DHCP_SERVER_PORT);
354 dhcpSecRule.setSecurityRulePortMax(DHCP_SERVER_PORT);
355 dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
356 if (ipSubnet.getIpv4Prefix() != null) {
357 dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
359 dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
364 private NeutronSecurityRule createUdpEgressSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId) {
365 NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
366 dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
367 dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
368 dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
369 if (consumerEpgId != null) {
370 dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
372 dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "_udp__" + ruleUuid);
373 dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
374 dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
375 if (ipSubnet.getIpv4Prefix() != null) {
376 dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
378 dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
383 private NeutronSecurityRule createDnsSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId) {
384 NeutronSecurityRule dnsSecRule = new NeutronSecurityRule();
385 dnsSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
386 dnsSecRule.setSecurityRuleTenantID(tenantId.getValue());
387 dnsSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
388 if (consumerEpgId != null) {
389 dnsSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
391 dnsSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "_dns__" + ruleUuid);
392 dnsSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
393 dnsSecRule.setSecurityRulePortMin(DNS_SERVER_PORT);
394 dnsSecRule.setSecurityRulePortMax(DNS_SERVER_PORT);
395 dnsSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
396 if (ipSubnet.getIpv4Prefix() != null) {
397 dnsSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
399 dnsSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
404 private NeutronSecurityRule createIcmpSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId,
406 NeutronSecurityRule icmpSecRule = new NeutronSecurityRule();
407 icmpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
408 icmpSecRule.setSecurityRuleTenantID(tenantId.getValue());
409 icmpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
410 if (consumerEpgId != null) {
411 icmpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
414 icmpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "_icmp__" + ruleUuid);
415 icmpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
417 icmpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "_icmp__" + ruleUuid);
418 icmpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
420 icmpSecRule.setSecurityRuleProtocol(NeutronUtils.ICMP);
421 if (ipSubnet.getIpv4Prefix() != null) {
422 icmpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
424 icmpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
430 * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort,
431 * org.opendaylight.neutron.spi.NeutronPort)
434 public int canUpdatePort(NeutronPort delta, NeutronPort original) {
435 LOG.trace("canUpdatePort - delta: {} original: {}", delta, original);
436 if (delta.getFixedIPs() == null || delta.getFixedIPs().isEmpty()) {
437 return StatusCode.OK;
439 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
440 List<Neutron_IPs> fixedIPs = delta.getFixedIPs();
441 if (fixedIPs != null && fixedIPs.size() > 1) {
442 LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
443 return StatusCode.BAD_REQUEST;
445 return StatusCode.OK;
449 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortUpdated(org.opendaylight.neutron.spi.NeutronPort)
452 public void neutronPortUpdated(NeutronPort port) {
453 LOG.trace("neutronPortUpdated - {}", port);
454 if (isRouterInterfacePort(port)) {
455 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
456 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
459 if (isRouterGatewayPort(port)) {
460 LOG.trace("Port is router gateway - {}", port.getID());
463 if (isFloatingIpPort(port)) {
464 LOG.trace("Port is floating ip - {}", port.getID());
467 if (Strings.isNullOrEmpty(port.getTenantID())) {
468 LOG.trace("REMOVE ME: Tenant is null - {}", port.getID());
472 ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
473 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
474 MacAddress macAddress = new MacAddress(port.getMacAddress());
475 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
476 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
477 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
483 Optional<Endpoint> potentionalEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
484 IidFactory.endpointIid(fwCtx.getL2BridgeDomain().getId(), macAddress), rTx);
485 if (!potentionalEp.isPresent()) {
486 LOG.warn("Illegal state - endpoint {} does not exist.", new EndpointKey(fwCtx.getL2BridgeDomain().getId(),
492 Endpoint ep = potentionalEp.get();
493 if (isEpIpDifferentThanPortFixedIp(ep, port) || isEpgDifferentThanSecGrp(ep, port)) {
494 UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(ep);
495 RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
497 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
498 if (!rpcResult.isSuccessful()) {
499 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
503 rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
504 if (!rpcResult.isSuccessful()) {
505 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
509 } catch (InterruptedException | ExecutionException e) {
510 LOG.error("addPort - RPC invocation failed.", e);
518 private boolean isEpIpDifferentThanPortFixedIp(Endpoint ep, NeutronPort port) {
519 List<L3Address> l3Addresses = ep.getL3Address();
520 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
521 if ((l3Addresses == null || l3Addresses.isEmpty()) && (fixedIPs == null || fixedIPs.isEmpty())) {
524 if (l3Addresses != null && !l3Addresses.isEmpty() && fixedIPs != null && !fixedIPs.isEmpty()) {
525 if (fixedIPs.get(0).getIpAddress().equals(Utils.getStringIpAddress(l3Addresses.get(0).getIpAddress()))) {
532 private boolean isEpgDifferentThanSecGrp(Endpoint ep, NeutronPort port) {
533 List<EndpointGroupId> epgIds = ep.getEndpointGroups();
534 List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
535 if ((epgIds == null || epgIds.isEmpty()) && (secGroups == null || secGroups.isEmpty())) {
538 if (epgIds != null && !epgIds.isEmpty() && secGroups != null && !secGroups.isEmpty()) {
539 if (epgIds.size() != secGroups.size()) {
542 Collection<EndpointGroupId> epgIdsFromSecGroups = Collections2.transform(secGroups,
543 new Function<NeutronSecurityGroup, EndpointGroupId>() {
546 public EndpointGroupId apply(NeutronSecurityGroup input) {
547 return new EndpointGroupId(input.getSecurityGroupUUID());
550 // order independent equals
551 Set<EndpointGroupId> one = new HashSet<>(epgIds);
552 Set<EndpointGroupId> two = new HashSet<>(epgIdsFromSecGroups);
553 if (one.equals(two)) {
561 * @see org.opendaylight.neutron.spi.INeutronPortAware#canDeletePort(org.opendaylight.neutron.spi.NeutronPort)
564 public int canDeletePort(NeutronPort port) {
565 LOG.trace("canDeletePort - {}", port);
566 // nothing to consider
567 return StatusCode.OK;
571 * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortDeleted(org.opendaylight.neutron.spi.NeutronPort)
574 public void neutronPortDeleted(NeutronPort port) {
575 LOG.trace("neutronPortDeleted - {}", port);
576 if (isRouterInterfacePort(port)) {
577 LOG.trace("Port is router interface - {} does nothing. {} handles router iface.",
578 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
581 if (isRouterGatewayPort(port)) {
582 LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
583 NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
586 if (isFloatingIpPort(port)) {
587 LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
588 floatingIpPortByDeviceId.remove(port.getDeviceID());
590 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
591 TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
592 L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
593 ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
594 boolean isFwCtxValid = validateForwardingCtx(fwCtx);
600 EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
601 deleteNeutronGbpMapping(port, epKey, rwTx);
602 UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
604 RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
605 if (!rpcResult.isSuccessful()) {
606 LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
608 } catch (InterruptedException | ExecutionException e) {
609 LOG.error("addPort - RPC invocation failed.", e);
614 private static void deleteNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
615 UniqueId portId = new UniqueId(port.getID());
616 if (isRouterInterfacePort(port)) {
617 LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
618 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
619 IidFactory.endpointByRouterInterfacePortIid(portId), rwTx);
620 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
621 IidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
622 } else if (isRouterGatewayPort(port)) {
623 LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
624 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
625 IidFactory.endpointByRouterGatewayPortIid(portId), rwTx);
626 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
627 IidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
628 } else if (isFloatingIpPort(port)) {
629 LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
630 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
631 IidFactory.endpointByFloatingIpPortIid(portId), rwTx);
632 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
633 IidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
635 LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
636 port.getDeviceOwner(), epKey);
637 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByPortIid(portId), rwTx);
638 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
639 IidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
643 private static RegisterL3PrefixEndpointInput createRegisterL3PrefixEndpointInput(EndpointL3PrefixKey key, List<EndpointL3Key> endpointL3Keys, TenantId tenantId) {
644 List<EndpointGroupId> epgIds = new ArrayList<>();
645 // each EP has to be in EPG ANY, except dhcp and router
646 epgIds.add(MappingUtils.EPG_ANY_ID);
648 List<EndpointL3Gateways> l3Gateways = new ArrayList<EndpointL3Gateways>();
649 for (EndpointL3Key epL3Key : endpointL3Keys) {
650 EndpointL3Gateways l3Gateway = new EndpointL3GatewaysBuilder().setIpAddress(epL3Key.getIpAddress())
651 .setL3Context(epL3Key.getL3Context())
653 l3Gateways.add(l3Gateway);
655 RegisterL3PrefixEndpointInputBuilder inputBuilder = new RegisterL3PrefixEndpointInputBuilder()
656 .setL3Context(key.getL3Context())
657 .setIpPrefix(key.getIpPrefix())
658 .setEndpointGroups(epgIds)
660 .setEndpointL3Gateways(l3Gateways)
661 .setTimestamp(System.currentTimeMillis());
662 return inputBuilder.build();
665 private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
666 List<EndpointGroupId> epgIds = new ArrayList<>();
667 // each EP has to be in EPG ANY, except dhcp and router
668 if (isDhcpPort(port)) {
669 epgIds.add(MappingUtils.EPG_DHCP_ID);
670 } else if (!containsSecRuleWithRemoteSecGroup(port.getSecurityGroups())) {
671 epgIds.add(MappingUtils.EPG_ANY_ID);
674 List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
675 if ((securityGroups == null || securityGroups.isEmpty())) {
676 if (!isDhcpPort(port)) {
678 "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
682 for (NeutronSecurityGroup secGrp : securityGroups) {
683 epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID()));
686 LocationType locationType = LocationType.Internal;
687 if(isRouterGatewayPort(port)) {
688 locationType = LocationType.External;
690 RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context(
691 fwCtx.getL2BridgeDomain().getId())
692 .setMacAddress(new MacAddress(port.getMacAddress()))
693 .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID())))
694 .setEndpointGroups(epgIds)
695 .addAugmentation(OfOverlayContextInput.class,
696 new OfOverlayContextInputBuilder()
697 .setPortName(createTapPortName(port))
698 .setLocationType(locationType)
700 .setTimestamp(System.currentTimeMillis());
701 List<Neutron_IPs> fixedIPs = port.getFixedIPs();
702 // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer
703 // will support l3-endpoints. Then we will register L2 and L3 endpoints separately.
704 Neutron_IPs firstIp = MappingUtils.getFirstIp(fixedIPs);
705 if (firstIp != null) {
706 inputBuilder.setNetworkContainment(new SubnetId(firstIp.getSubnetUUID()));
707 L3Address l3Address = new L3AddressBuilder().setIpAddress(Utils.createIpAddress(firstIp.getIpAddress()))
708 .setL3Context(fwCtx.getL3Context().getId())
710 inputBuilder.setL3Address(ImmutableList.of(l3Address));
712 if (!Strings.isNullOrEmpty(port.getName())) {
715 return inputBuilder.build();
718 private static boolean containsSecRuleWithRemoteSecGroup(List<NeutronSecurityGroup> secGroups) {
719 if (secGroups == null) {
722 for (NeutronSecurityGroup secGroup : secGroups) {
723 boolean containsSecRuleWithRemoteSecGroup = containsSecRuleWithRemoteSecGroup(secGroup);
724 if (containsSecRuleWithRemoteSecGroup) {
731 private static boolean containsSecRuleWithRemoteSecGroup(NeutronSecurityGroup secGroup) {
732 List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
733 if (secRules == null) {
736 for (NeutronSecurityRule secRule : secRules) {
737 if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
744 private static Name createTapPortName(NeutronPort port) {
745 return new Name("tap" + port.getID().substring(0, 11));
748 private static boolean isDhcpPort(NeutronPort port) {
749 return DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
752 private static boolean isRouterInterfacePort(NeutronPort port) {
753 return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner());
756 private static boolean isRouterGatewayPort(NeutronPort port) {
757 return DEVICE_OWNER_ROUTER_GATEWAY.equals(port.getDeviceOwner());
760 private static boolean isFloatingIpPort(NeutronPort port) {
761 return DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner());
764 private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) {
765 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
766 L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build();
767 inputBuilder.setL2(ImmutableList.of(l2Ep));
768 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
769 // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
770 // be registered separately.
771 if (ep.getL3Address() != null && !ep.getL3Address().isEmpty()) {
772 List<L3> l3Eps = new ArrayList<>();
773 for (L3Address ip : ep.getL3Address()) {
774 l3Eps.add(new L3Builder().setL3Context(ip.getL3Context()).setIpAddress(ip.getIpAddress()).build());
776 inputBuilder.setL3(l3Eps);
778 return inputBuilder.build();
781 private UnregisterEndpointInput createUnregisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
782 UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
783 L2 l2Ep = new L2Builder().setL2Context(fwCtx.getL2BridgeDomain().getId())
784 .setMacAddress(new MacAddress(port.getMacAddress()))
786 inputBuilder.setL2(ImmutableList.of(l2Ep));
787 // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
788 // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
789 // be registered separately.
790 if (port.getFixedIPs() != null && !port.getFixedIPs().isEmpty()) {
791 inputBuilder.setL3(createL3s(port.getFixedIPs(), fwCtx.getL3Context().getId()));
793 return inputBuilder.build();
796 private List<L3> createL3s(List<Neutron_IPs> neutronIps, L3ContextId l3ContextId) {
797 List<L3> l3s = new ArrayList<>();
798 for (Neutron_IPs fixedIp : neutronIps) {
799 String ip = fixedIp.getIpAddress();
800 L3 l3 = new L3Builder().setIpAddress(Utils.createIpAddress(ip)).setL3Context(l3ContextId).build();
806 public static UniqueId getFloatingIpPortIdByDeviceId(String deviceId) {
807 return floatingIpPortByDeviceId.get(deviceId);