/*
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.MetadataService;
import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils;
import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
import org.opendaylight.groupbasedpolicy.util.IidFactory;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
public class NeutronPortAware implements NeutronAware<Port> {
private static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
public static final InstanceIdentifier<Port> PORT_WILDCARD_IID =
InstanceIdentifier.builder(Neutron.class).child(Ports.class).child(Port.class).build();
private final DataBroker dataProvider;
private final EndpointRegistrator epRegistrator;
private final IpPrefix metadataIpPrefix;
public NeutronPortAware(DataBroker dataProvider, EndpointRegistrator epRegistrator,
@Nullable IpPrefix metadataIpPrefix) {
this.dataProvider = checkNotNull(dataProvider);
this.epRegistrator = checkNotNull(epRegistrator);
this.metadataIpPrefix = checkNotNull(metadataIpPrefix);
}
@Override public void onCreated(Port createdItem, Neutron neutron) {
onCreated(createdItem, neutron, true);
}
public void onCreated(Port port, Neutron neutron, boolean addBaseEpMapping) {
LOG.trace("created port - {}", port);
if (PortUtils.isRouterInterfacePort(port)) {
LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
// router interface port can have only one IP
Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
if (!potentialPortIpWithSubnet.isPresent()) {
LOG.warn("Illegal state - router interface port does not contain fixed IPs {}",
port);
return;
}
FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
ContextId routerL3Context = new ContextId(port.getDeviceId());
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
AddressEndpointKey addrEpKey = new AddressEndpointKey(port.getMacAddress().getValue(),
MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
UniqueId portId = new UniqueId(port.getUuid().getValue());
addBaseEndpointMappings(addrEpKey, portId, rwTx);
// Add Qrouter and VPProuter port as Endpoint
if (port.getAugmentation(PortBindingExtension.class) != null &&
PortUtils.DEVICE_VIF_TYPE.equals(port.getAugmentation(PortBindingExtension.class).getVifType())) {
LOG.trace("Port is QRouter port: {}", port.getUuid().getValue());
Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
if (!firstFixedIps.isPresent()) {
LOG.warn("QRouter port does not have an IP address. {}", port);
return;
}
FixedIps ipWithSubnet = firstFixedIps.get();
NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
epgsFromSecGroups.add(NetworkService.EPG_ID);
// BUILD BASE ENDPOINT
AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(port, networkContainment,
epgsFromSecGroups);
AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(port, networkContainment,
epgsFromSecGroups, neutron);
setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
// BUILD ENDPOINT
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder
epInBuilder =
createEndpointRegFromPort(
port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
registerBaseEndpointAndStoreMapping(
ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx, addBaseEpMapping);
registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
}
// change L3Context for all EPs with same subnet as router port
changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), neutron);
// set L3Context as parent for bridge domain which is parent of subnet
TenantId tenantId = new TenantId(port.getTenantId().getValue());
Optional<Subnet> potentialRouterPortSubnet = SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), neutron.getSubnets());
if (!potentialRouterPortSubnet.isPresent()) {
LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}",
port);
return;
}
Subnet routerPortSubnet = potentialRouterPortSubnet.get();
ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
ForwardingContext l2Bd = new ForwardingContextBuilder().setContextId(l2BdId)
.setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
.setParent(MappingUtils.createParent(routerL3Context, MappingUtils.L3_CONTEXT))
.build();
rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
// set virtual router IP for subnet
NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(routerPortSubnet, neutron, null);
rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
// does the same for tenant forwarding domains
processTenantForwarding(routerPortSubnet, routerL3Context, portIpWithSubnet, tenantId, rwTx);
DataStoreHelper.submitToDs(rwTx);
} else if (PortUtils.isDhcpPort(port)) {
// process as normal port but put it to DHCP group
LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
if (!firstFixedIps.isPresent()) {
LOG.warn("DHCP port does not have an IP address. {}", port);
return;
}
FixedIps ipWithSubnet = firstFixedIps.get();
NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
epgsFromSecGroups.add(NetworkService.EPG_ID);
AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(port, networkContainment,
Collections.emptyList());
AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(port, networkContainment,
epgsFromSecGroups, neutron);
setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createEndpointRegFromPort(
port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
registerBaseEndpointAndStoreMapping(
ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx, addBaseEpMapping);
AddressEndpointRegBuilder metadataEp = createBasicL3AddrEpInputBuilder(cloneMetadataPortFromDhcpPort(port, metadataIpPrefix), networkContainment,
Lists.newArrayList(MetadataService.EPG_ID), neutron);
setParentChildRelationshipForEndpoints(metadataEp, l2BaseEp);
registerBaseEndpointAndStoreMapping(
ImmutableList.of(metadataEp.build()), port, rwTx, true);
registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
DataStoreHelper.submitToDs(rwTx);
} else if (PortUtils.isNormalPort(port)) {
LOG.trace("Port is normal port: {}", port.getUuid().getValue());
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = null;
AddressEndpointRegBuilder l2BaseEp;
AddressEndpointRegBuilder l3BaseEp = null;
Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
epgsFromSecGroups.add(NetworkClient.EPG_ID);
if (firstFixedIps.isPresent()) {
// endpoint has only one network containment therefore only first IP is used
FixedIps ipWithSubnet = firstFixedIps.get();
NetworkDomainId containment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
epInBuilder = createEndpointRegFromPort(port, ipWithSubnet, containment, epgsFromSecGroups, neutron);
l2BaseEp = createBasicMacAddrEpInputBuilder(port,
containment, epgsFromSecGroups);
l3BaseEp = createBasicL3AddrEpInputBuilder(port, containment, epgsFromSecGroups, neutron);
setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
} else {
NetworkDomainId containment = new NetworkDomainId(port.getNetworkId().getValue());
epInBuilder = createEndpointRegFromPort(port, null, containment, epgsFromSecGroups, neutron);
l2BaseEp = createBasicMacAddrEpInputBuilder(port, containment, epgsFromSecGroups);
}
List<AddressEndpointReg> baseEpRegs = new ArrayList<>();
baseEpRegs.add(l2BaseEp.build());
if (l3BaseEp != null) {
baseEpRegs.add(l3BaseEp.build());
}
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
registerBaseEndpointAndStoreMapping(baseEpRegs, port, rwTx, addBaseEpMapping);
registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
DataStoreHelper.submitToDs(rwTx);
} else if (PortUtils.isRouterGatewayPort(port)) {
// do nothing because actual trigger is attaching of port to router
LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
} else if (PortUtils.isFloatingIpPort(port)) {
// do nothing because trigger is floating IP
LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
} else {
LOG.warn("Unknown port: {}", port);
}
}
private Port cloneMetadataPortFromDhcpPort(Port port, IpPrefix metadataPrefix) {
IpAddress metadataIp = MappingUtils.ipPrefixToIpAddress(metadataPrefix);
List<FixedIps> metadataIps = port.getFixedIps().stream().map(fi -> {
FixedIpsKey key = new FixedIpsKey(metadataIp, fi.getKey().getSubnetId());
return new FixedIpsBuilder(fi).setKey(key).setIpAddress(metadataIp).build();
}).collect(Collectors.toList());
return new PortBuilder(port).setFixedIps(metadataIps).build();
}
private void setParentChildRelationshipForEndpoints(AddressEndpointRegBuilder parentEp,
AddressEndpointRegBuilder childEp) {
childEp.setParentEndpointChoice(new ParentEndpointCaseBuilder().setParentEndpoint(
ImmutableList.<ParentEndpoint>of(createParentEndpoint(parentEp))).build());
parentEp.setChildEndpoint(ImmutableList.<ChildEndpoint>of(createChildEndpoint(childEp)));
}
@Deprecated
private void processTenantForwarding(Subnet routerPortSubnet, ContextId routerL3Context, FixedIps portIpWithSubnet,
TenantId tenantId, ReadWriteTransaction rwTx) {
L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(new L3ContextId(routerL3Context)).build();
rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
// set virtual router IP for subnet
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnet = NeutronSubnetAware.createTenantSubnet(
routerPortSubnet, portIpWithSubnet.getIpAddress());
rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet);
}
/**
* Registers endpoint from {@link Port} and method parameters.
* Always creates registration input for L2 endpoint.
* Creates registration input for L3 endpoint if fixedIps argument is not null.
*/
@Deprecated
private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createEndpointRegFromPort(
Port port, FixedIps fixedIps, NetworkDomainId networkContainment, List<EndpointGroupId> endpointGroupIds, Neutron neutron) {
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createBasicEndpointInputBuilder(
port).setNetworkContainment(networkContainment);
if (fixedIps != null) {
L3Address l3Address = resolveL3AddressFromPort(port, fixedIps, neutron);
epInBuilder.setL3Address(ImmutableList.of(l3Address));
}
epInBuilder.setEndpointGroups(endpointGroupIds);
return epInBuilder;
}
private void changeL3ContextForEpsInSubnet(Uuid subnetUuid, Neutron neutron) {
if (neutron == null) {
LOG.debug("No new data are written, there is no L3 context in subnet {} to update", subnetUuid);
return;
}
Set<Port> portsInSameSubnet = PortUtils.findPortsBySubnet(subnetUuid, neutron.getPorts());
for (Port portInSameSubnet : portsInSameSubnet) {
if (PortUtils.isNormalPort(portInSameSubnet) || PortUtils.isDhcpPort(portInSameSubnet)
|| PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
// endpoints are created only from neutron normal port or DHCP port
Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(portInSameSubnet);
if (firstFixedIps.isPresent()) {
// endpoint has only one network containment therefore only first IP is used
FixedIps ipWithSubnet = firstFixedIps.get();
List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
if (PortUtils.isDhcpPort(portInSameSubnet) || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) {
endpointGroupIds.add(NetworkService.EPG_ID);
} else if (PortUtils.isNormalPort(portInSameSubnet)) {
endpointGroupIds.add(NetworkClient.EPG_ID);
}
NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(portInSameSubnet,
networkContainment, endpointGroupIds);
AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(portInSameSubnet,
networkContainment, endpointGroupIds, neutron);
setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
AddressEndpointUnreg addrEpUnreg = new AddressEndpointUnregBuilder().setAddress(l3BaseEp.getAddress())
.setAddressType(l3BaseEp.getAddressType())
.setContextId(new ContextId(portInSameSubnet.getNetworkId().getValue()))
.setContextType(l3BaseEp.getContextType())
.build();
epRegistrator.unregisterEndpoint(addrEpUnreg);
RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder()
.setAddressEndpointReg(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build())).build();
epRegistrator.registerEndpoint(regBaseEpInput);
modifyL3ContextForEndpoints(portInSameSubnet, ipWithSubnet, l3BaseEp.getContextId());
}
}
}
}
private ChildEndpoint createChildEndpoint(AddressEndpointRegBuilder builder) {
return new ChildEndpointBuilder().setAddress(builder.getAddress())
.setAddressType(builder.getAddressType())
.setContextId(builder.getContextId())
.setContextType(builder.getContextType())
.build();
}
private ParentEndpoint createParentEndpoint(AddressEndpointRegBuilder builder) {
return new ParentEndpointBuilder().setAddress(builder.getAddress())
.setAddressType(builder.getAddressType())
.setContextId(builder.getContextId())
.setContextType(builder.getContextType())
.build();
}
@Deprecated
private void modifyL3ContextForEndpoints(Port port, FixedIps resolvedPortFixedIp, ContextId newContextId) {
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createBasicEndpointInputBuilder(port);
epInBuilder.setNetworkContainment(new NetworkDomainId(resolvedPortFixedIp.getSubnetId().getValue()));
L3Address l3Address = new L3AddressBuilder().setL3Context(new L3ContextId(newContextId))
.setIpAddress(resolvedPortFixedIp.getIpAddress())
.build();
epInBuilder.setL3Address(ImmutableList.of(l3Address));
List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
epgsFromSecGroups.add(NetworkClient.EPG_ID);
epInBuilder.setEndpointGroups(epgsFromSecGroups);
epRegistrator.registerEndpoint(epInBuilder.build());
// unregister L3EP
L3ContextId oldL3Context = new L3ContextId(port.getNetworkId().getValue());
L3 l3 = new L3Builder().setL3Context(oldL3Context).setIpAddress(resolvedPortFixedIp.getIpAddress()).build();
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput epUnreg = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder().setL3(
ImmutableList.of(l3))
.build();
epRegistrator.unregisterEndpoint(epUnreg);
}
private AddressEndpointRegBuilder createBasicMacAddrEpInputBuilder(Port port,
NetworkDomainId networkContainment, @Nullable List<EndpointGroupId> endpointGroupsToAdd) {
AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
.setAddress(port.getMacAddress().getValue())
.setAddressType(MacAddressType.class)
.setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
.setContextId(new ContextId(port.getNetworkId().getValue()))
.setTenant(new TenantId(port.getTenantId().getValue()))
.setTimestamp(System.currentTimeMillis());
List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
addrEpbuilder.setEndpointGroup(epgs);
if (networkContainment != null) {
addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment(
new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
.setNetworkDomainType(MappingUtils.SUBNET)
.build()).build());
}
return addrEpbuilder;
}
private AddressEndpointRegBuilder createBasicL3AddrEpInputBuilder(Port port, NetworkDomainId networkContainment,
@Nullable List<EndpointGroupId> endpointGroupsToAdd, Neutron neutron) {
Optional<FixedIps> firstFixedIps = PortUtils.resolveFirstFixedIps(port);
if (!firstFixedIps.isPresent()) {
throw new IllegalStateException("Failed to resolve FixedIps for port " + port.getKey()
+ ". Cannot register L3 Address endpoint.");
}
ContextId resolveL3ContextForPort = resolveL3ContextForPort(port, port.getFixedIps().get(0), neutron);
AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class)
.setAddress(MappingUtils.ipAddressToStringIpPrefix(firstFixedIps.get().getIpAddress()))
.setAddressType(IpPrefixType.class)
.setContextType(MappingUtils.L3_CONTEXT)
.setContextId(resolveL3ContextForPort)
.setTenant(new TenantId(port.getTenantId().getValue()))
.setTimestamp(System.currentTimeMillis());
List<EndpointGroupId> epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd);
addrEpbuilder.setEndpointGroup(epgs);
if (networkContainment != null) {
addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment(
new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment)
.setNetworkDomainType(MappingUtils.SUBNET)
.build()).build());
}
return addrEpbuilder;
}
private List<EndpointGroupId> concatEndpointGroups(List<Uuid> securityGroups,
@Nullable List<EndpointGroupId> endpointGroupsToAdd) {
List<EndpointGroupId> epgs = new ArrayList<>();
if (securityGroups != null) {
for (Uuid sgId : securityGroups) {
epgs.add(new EndpointGroupId(sgId.getValue()));
}
}
if (endpointGroupsToAdd != null) {
epgs.addAll(endpointGroupsToAdd);
}
return epgs;
}
@Deprecated
private static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createBasicEndpointInputBuilder(
Port port) {
return new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder().setL2Context(
new L2BridgeDomainId(port.getNetworkId().getValue()))
.setMacAddress(new MacAddress(port.getMacAddress().getValue()))
.setTenant(new TenantId(port.getTenantId().getValue()))
.setTimestamp(System.currentTimeMillis());
}
private static List<EndpointGroupId> resolveEpgIdsFromSecGroups(@Nullable List<Uuid> securityGroups) {
List<EndpointGroupId> epgIds = new ArrayList<>();
if ((securityGroups == null || securityGroups.isEmpty())) {
return epgIds;
}
for (Uuid secGrp : securityGroups) {
epgIds.add(new EndpointGroupId(secGrp.getValue()));
}
return epgIds;
}
@Deprecated
private void registerEndpointAndStoreMapping(
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput regEpInput,
Port port, ReadWriteTransaction rwTx) {
boolean isRegisteredEndpoint = epRegistrator.registerEndpoint(regEpInput);
if (!isRegisteredEndpoint) {
LOG.error("Failed to register endpoint: {}", regEpInput);
return;
}
UniqueId portId = new UniqueId(port.getUuid().getValue());
EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress(
port.getMacAddress().getValue()));
LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid()
.getValue(), port.getDeviceOwner(), epKey);
EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort, true);
PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
rwTx.put(LogicalDatastoreType.OPERATIONAL,
NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint,
true);
}
@Deprecated
private void unregisterEndpointAndRemoveMapping(
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput unregEpInput,
Port port, ReadWriteTransaction rwTx) {
boolean isUnregisteredEndpoint = epRegistrator.unregisterEndpoint(unregEpInput);
if (isUnregisteredEndpoint) {
UniqueId portId = new UniqueId(port.getUuid().getValue());
EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress(
port.getMacAddress().getValue()));
LOG.trace("Removing Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid()
.getValue(), port.getDeviceOwner(), epKey);
DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
NeutronGbpIidFactory.endpointByPortIid(portId), rwTx);
DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
}
}
private void registerBaseEndpointAndStoreMapping(List<AddressEndpointReg> addrEpRegs, Port port,
WriteTransaction wTx, boolean addBaseEpMappings) {
RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder().setAddressEndpointReg(addrEpRegs)
.build();
boolean isRegisteredBaseEndpoint = epRegistrator.registerEndpoint(regBaseEpInput);
if (!isRegisteredBaseEndpoint) {
LOG.error("Failed to register address endpoint: {}", addrEpRegs);
return;
}
for (AddressEndpointReg addrEpReg : addrEpRegs) {
if (MappingUtils.L2_BRDIGE_DOMAIN.equals(addrEpReg.getContextType()) && addBaseEpMappings) {
UniqueId portId = new UniqueId(port.getUuid().getValue());
LOG.trace("Adding Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
port.getUuid());
AddressEndpointKey addrEpKey = new AddressEndpointKey(addrEpReg.getAddress(),
addrEpReg.getAddressType(), addrEpReg.getContextId(), addrEpReg.getContextType());
addBaseEndpointMappings(addrEpKey, portId, wTx);
}
}
}
private void addBaseEndpointMappings(AddressEndpointKey addrEpKey, UniqueId portId, WriteTransaction wTx) {
BaseEndpointByPort baseEndpointByPort = MappingFactory.createBaseEndpointByPort(addrEpKey, portId);
wTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.baseEndpointByPortIid(portId),
baseEndpointByPort, true);
PortByBaseEndpoint portByBaseEndpoint = MappingFactory.createPortByBaseEndpoint(portId, addrEpKey);
wTx.put(LogicalDatastoreType.OPERATIONAL,
NeutronGbpIidFactory.portByBaseEndpointIid(new PortByBaseEndpointKey(
portByBaseEndpoint.getKey())), portByBaseEndpoint, true);
}
private void unregisterEndpointAndRemoveMapping(UnregisterEndpointInput baseEpUnreg, Port port,
ReadWriteTransaction rwTx, boolean removeBaseEpMappings) {
boolean isUnregisteredBaseEndpoint = epRegistrator.unregisterEndpoint(baseEpUnreg);
if (isUnregisteredBaseEndpoint) {
UniqueId portId = new UniqueId(port.getUuid().getValue());
PortByBaseEndpointKey portByBaseEndpointKey = new PortByBaseEndpointKey(port.getMacAddress().getValue(),
MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
LOG.trace("Removing Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}",
port.getUuid().getValue(), port.getDeviceOwner(), portByBaseEndpointKey);
if (removeBaseEpMappings) {
removeBaseEndpointMappings(portByBaseEndpointKey, portId, rwTx);
}
}
}
private void removeBaseEndpointMappings(PortByBaseEndpointKey portByBaseEndpointKey, UniqueId portId, ReadWriteTransaction rwTx) {
DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
NeutronGbpIidFactory.baseEndpointByPortIid(portId), rwTx);
DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
NeutronGbpIidFactory.portByBaseEndpointIid(portByBaseEndpointKey), rwTx);
}
@Override
public void onUpdated(Port oldPort, Port newPort, Neutron oldNeutron, Neutron newNeutron) {
LOG.trace("updated port - OLD: {}\nNEW: {}", oldPort, newPort);
onDeleted(oldPort, oldNeutron, newNeutron, false);
onCreated(newPort, newNeutron, false);
}
@Override public void onDeleted(Port deletedItem, Neutron oldNeutron, Neutron newNeutron) {
onDeleted(deletedItem, oldNeutron, newNeutron, true);
}
public void onDeleted(Port port, Neutron oldNeutron, Neutron newNeutron, boolean removeBaseEpMapping) {
LOG.trace("deleted port - {}", port);
if (PortUtils.isRouterInterfacePort(port)) {
LOG.trace("Port is router interface port: {}", port.getUuid().getValue());
// router interface port can have only one IP
Optional<FixedIps> potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port);
if (!potentialPortIpWithSubnet.isPresent()) {
LOG.warn("Illegal state - router interface port does not contain fixed IPs {}",
port);
return;
}
FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
L3ContextId l3Context = new L3ContextId(port.getNetworkId().getValue());
// change L3Context for all new EPs with same subnet as router port
changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), newNeutron);
// set L3Context as parent for bridge domain which is parent of subnet
TenantId tenantId = new TenantId(port.getTenantId().getValue());
Optional<Subnet> potentialRouterPortSubnet = SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(),
oldNeutron.getSubnets());
if (!potentialRouterPortSubnet.isPresent()) {
LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", port);
return;
}
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
Subnet routerPortSubnet = potentialRouterPortSubnet.get();
modifyForwardingOnDelete(routerPortSubnet, l3Context, tenantId, rwTx);
ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue());
ForwardingContext fwdCtx = new ForwardingContextBuilder().setContextId(l2BdId)
.setContextType(MappingUtils.L2_BRDIGE_DOMAIN)
.setParent(MappingUtils.createParent(l3Context, MappingUtils.L3_CONTEXT))
.build();
rwTx.merge(LogicalDatastoreType.CONFIGURATION,
L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron, null);
rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()),
subnet);
unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping);
DataStoreHelper.submitToDs(rwTx);
} else if (PortUtils.isDhcpPort(port)) {
LOG.trace("Port is DHCP port: {}", port.getUuid().getValue());
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping);
DataStoreHelper.submitToDs(rwTx);
} else if (PortUtils.isNormalPort(port)) {
LOG.trace("Port is normal port: {}", port.getUuid().getValue());
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping);
DataStoreHelper.submitToDs(rwTx);
} else if (PortUtils.isRouterGatewayPort(port)) {
// do nothing because actual trigger is detaching of port from router
LOG.trace("Port is router gateway port: {}", port.getUuid().getValue());
} else if (PortUtils.isFloatingIpPort(port)) {
// do nothing because trigger is floating IP
LOG.trace("Port is floating ip: {}", port.getUuid().getValue());
} else {
LOG.warn("Unknown port: {}", port);
}
}
@Deprecated
private void modifyForwardingOnDelete(Subnet routerPortSubnet, L3ContextId l3contextId, TenantId tenantId, ReadWriteTransaction rwTx) {
L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue());
L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(l3contextId).build();
rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd);
// remove virtual router IP for subnet
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet tenantSubnet = NeutronSubnetAware.createTenantSubnet(routerPortSubnet, null);
rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, tenantSubnet.getId()), tenantSubnet);
}
private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput createUnregisterBaseEndpointInput(
Port port, Neutron neutron) {
UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
List<AddressEndpointUnreg> list = new ArrayList<>();
AddressEndpointUnregBuilder addrL2EpUnregBuilder = new AddressEndpointUnregBuilder();
addrL2EpUnregBuilder.setAddress(port.getMacAddress().getValue())
.setAddressType(MacAddressType.class)
.setContextId(new ContextId(port.getNetworkId().getValue()))
.setContextType(MappingUtils.L2_BRDIGE_DOMAIN);
list.add(addrL2EpUnregBuilder.build());
Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
if (potentialFirstIp.isPresent()) {
ContextId l3ContextId = resolveL3ContextForPort(port, potentialFirstIp.get(), neutron);
AddressEndpointUnregBuilder addrL3EpUnregBuilder = new AddressEndpointUnregBuilder();
addrL3EpUnregBuilder.setAddress(MappingUtils.ipAddressToStringIpPrefix(potentialFirstIp.get().getIpAddress()))
.setAddressType(IpPrefixType.class)
.setContextId(l3ContextId)
.setContextType(L3Context.class);
list.add(addrL3EpUnregBuilder.build());
}
inputBuilder.setAddressEndpointUnreg(list);
return inputBuilder.build();
}
@Deprecated
private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput createUnregisterEndpointInput(
Port port, Neutron neutron) {
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder inputBuilder =
new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder();
L2 l2Ep = new L2Builder().setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue()))
.setMacAddress(new MacAddress(port.getMacAddress().getValue()))
.build();
inputBuilder.setL2(ImmutableList.of(l2Ep));
// we've registered EP with only first IP so remove only EP with first IP
Optional<FixedIps> potentialFirstIp = PortUtils.resolveFirstFixedIps(port);
if (potentialFirstIp.isPresent()) {
FixedIps firstIp = potentialFirstIp.get();
L3Address l3Address = resolveL3AddressFromPort(port, firstIp, neutron);
L3 l3 = new L3Builder().setIpAddress(l3Address.getIpAddress())
.setL3Context(l3Address.getL3Context())
.build();
inputBuilder.setL3(ImmutableList.of(l3));
}
return inputBuilder.build();
}
@Deprecated
private static L3Address resolveL3AddressFromPort(Port port, FixedIps portFixedIPs, Neutron neutron) {
Set<Port> routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts());
for (Port routerIfacePort : routerIfacePorts) {
Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId();
// if port is in the same subnet as router interface then we want to use L3Context of
// router
if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) {
L3ContextId epL3ContextId = new L3ContextId(routerIfacePort.getDeviceId());
LOG.trace("Router interface port was found in the same subnet as port have {}", port);
return new L3AddressBuilder().setL3Context(epL3ContextId)
.setIpAddress(portFixedIPs.getIpAddress())
.build();
}
}
return new L3AddressBuilder().setL3Context(new L3ContextId(port.getNetworkId().getValue()))
.setIpAddress(portFixedIPs.getIpAddress())
.build();
}
private static ContextId resolveL3ContextForPort(Port port, FixedIps portFixedIPs, Neutron neutron) {
Set<Port> routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts());
for (Port routerIfacePort : routerIfacePorts) {
Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId();
// if port is in the same subnet as router interface then we want to use L3Context of
// router
if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) {
LOG.trace("Router interface port was found in the same subnet as port have {}", port);
return new ContextId(routerIfacePort.getDeviceId());
}
}
return new ContextId(port.getNetworkId().getValue());
}
}