import com.google.common.annotations.VisibleForTesting;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.CommonEndpointFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
if (!equalsCommonEndpointFields(a, b)) {
return false;
}
+ if (!equalsAugmentations(a, b)) {
+ return false;
+ }
return true;
}
return t.hashCode();
}
};
-
@VisibleForTesting
static final Equivalence<ContainmentEndpoint> CONT_EP_EQ = new Equivalence<ContainmentEndpoint>() {
return t.hashCode();
}
};
-
@VisibleForTesting
static final Equivalence<AddressEndpointLocation> ADDR_EP_LOC_EQ =
new Equivalence<AddressEndpointLocation>() {
return t.hashCode();
}
};
-
@VisibleForTesting
static final Equivalence<ContainmentEndpointLocation> CONT_EP_LOC_EQ =
new Equivalence<ContainmentEndpointLocation>() {
return t.hashCode();
}
};
-
@VisibleForTesting
static final Equivalence<ForwardingByTenant> FWD_BY_TENANT_EQ = new Equivalence<ForwardingByTenant>() {
private DtoEquivalenceUtils() {}
+ private static boolean equalsAugmentations(AddressEndpoint a, AddressEndpoint b) {
+ if (a.getAugmentation(NatAddress.class) != null && b.getAugmentation(NatAddress.class) != null) {
+ if (!a.getAugmentation(NatAddress.class)
+ .getNatAddress()
+ .equals(b.getAugmentation(NatAddress.class).getNatAddress())) {
+ return false;
+ }
+ } else if (a.getAugmentation(NatAddress.class) != null || b.getAugmentation(NatAddress.class) != null) {
+ return false;
+ }
+ return true;
+ }
+
static boolean equalsAddressEpByKey(@Nullable Map<AddressEndpointKey, AddressEndpoint> o1,
@Nullable Map<AddressEndpointKey, AddressEndpoint> o2) {
return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_EQ);
if (addrEpWithLocAug != null) {
addrEpWithLoc.addAugmentation(addrEpWithLocAug.getKey(), addrEpWithLocAug.getValue());
}
- if (ep.getAugmentation(NatAddress.class) != null) {
- NatAddress natAddr = ep.getAugmentation(NatAddress.class);
- addrEpWithLoc.addAugmentation(NatAddressRenderer.class,
- new NatAddressRendererBuilder().setNatAddress(natAddr.getNatAddress()).build());
- }
+ }
+ if (ep.getAugmentation(NatAddress.class) != null) {
+ NatAddress natAddr = ep.getAugmentation(NatAddress.class);
+ addrEpWithLoc.addAugmentation(NatAddressRenderer.class,
+ new NatAddressRendererBuilder().setNatAddress(natAddr.getNatAddress()).build());
}
return addrEpWithLoc.build();
}
BaseEndpointService baseEpService) {
EndpointRegistrator epRegistrator = new EndpointRegistrator(epService, baseEpService);
networkAware = new NeutronNetworkAware(dataProvider);
- securityGroupAware = new NeutronSecurityGroupAware(dataProvider);
securityRuleAware = new NeutronSecurityRuleAware(dataProvider);
+ securityGroupAware = new NeutronSecurityGroupAware(dataProvider, securityRuleAware);
subnetAware = new NeutronSubnetAware(dataProvider, epRegistrator);
portAware = new NeutronPortAware(dataProvider, epRegistrator);
routerAware = new NeutronRouterAware(dataProvider, epRegistrator);
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.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+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.l3endpoint.rev151217.NatAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddressBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.Floatingips;
@Override
public void onCreated(Floatingip floatingIP, Neutron neutron) {
- LOG.trace("created floatinIp - {}", floatingIP);
+ LOG.trace("created floatingIp - {}", floatingIP);
}
@Override
}
@Deprecated
- private void syncNatForEndpoint(ReadWriteTransaction rwTx, Floatingip newFloatingIp, Floatingip oldFloatingIp) {
+ private void syncNatForEndpoint(ReadWriteTransaction rwTx, Floatingip oldFloatingIp, Floatingip newFloatingIp) {
IpAddress oldEpIp = oldFloatingIp.getFixedIpAddress();
IpAddress newEpIp = newFloatingIp.getFixedIpAddress();
IpAddress epNatIp = newFloatingIp.getFloatingIpAddress();
L3ContextId routerL3ContextId = new L3ContextId(newFloatingIp.getRouterId().getValue());
+
+ if (oldEpIp != null) {
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.l3EndpointIid(routerL3ContextId, oldEpIp).augmentation(NatAddress.class), rwTx);
+ }
+
if (epNatIp != null && newEpIp != null) {
NatAddress nat = new NatAddressBuilder().setNatAddress(epNatIp).build();
+ AddressEndpointKey aek =
+ new AddressEndpointKey(newEpIp.getIpv4Address().getValue() + "/32", IpPrefixType.class,
+ routerL3ContextId, L3Context.class);
+ LOG.info("Adding NAT augmentation {} for base-endpoint {}", epNatIp, aek);
+ rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek)
+ .augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress.class),
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddressBuilder()
+ .setNatAddress(epNatIp)
+ .build(), true);
rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.l3EndpointIid(routerL3ContextId, newEpIp)
.augmentation(NatAddress.class), nat, true);
}
- if (oldEpIp != null) {
- DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
- IidFactory.l3EndpointIid(routerL3ContextId, oldEpIp).augmentation(NatAddress.class), rwTx);
- }
}
@Override
.build();
rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
// set virtual router IP for subnet
- NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(
- routerPortSubnet, neutron);
+ NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(routerPortSubnet, neutron, null);
rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
// does the same for tenant forwarding domains
.build();
rwTx.merge(LogicalDatastoreType.CONFIGURATION,
L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
- NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron);
+ NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron, null);
rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()),
subnet);
unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
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.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwardingBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.Subnet;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.Prefixes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.PrefixesBuilder;
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.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
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.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
// router can have only one external network
FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0);
- Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet>
+ potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
if (!potentialSubnet.isPresent()) {
LOG.warn("Illegal state - Subnet {} does not exist for router {}.",
ipWithSubnetFromGwPort.getSubnetId(), newRouter);
rwTx.cancel();
return;
}
- IpPrefix gatewayIp = MappingUtils.ipAddressToIpPrefix(potentialSubnet.get().getGatewayIp());
- boolean registeredExternalGateway = registerExternalGateway(tenantId, gatewayIp,
- routerL3CtxId, new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue()));
+ tenantId = new TenantId(potentialSubnet.get().getTenantId().getValue());
+ IpAddress gwIp = potentialSubnet.get().getGatewayIp();
+ IpPrefix gatewayIp = MappingUtils.ipAddressToIpPrefix(gwIp);
+ NetworkDomainId subnetId = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue());
+ boolean registeredExternalGateway = registerExternalGateway(tenantId, gatewayIp, routerL3CtxId, subnetId);
if (!registeredExternalGateway) {
LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort);
rwTx.cancel();
return;
}
addNeutronExtGwGbpMapping(routerL3CtxId, gatewayIp, rwTx);
- NetworkDomain subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId()
- .getValue()));
- rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()),
- subnetDomain);
+ NetworkDomain subnetDomain;
+ List<Prefixes> defaultPrefixes =
+ Collections.singletonList(new PrefixesBuilder().setPrefix(MappingUtils.DEFAULT_ROUTE).build());
+ // if subnet is in external network then create subnet with IP from GW port as its virtual router IP
+ // else use subnet gateway as virtual router IP.
+ if (isSubnetInExternalNetwork(newNeutron.getNetworks().getNetwork(),
+ potentialSubnet.get().getNetworkId())) {
+ subnetDomain = createSubnetWithVirtualRouterIp(
+ MappingUtils.ipAddressToIpPrefix(ipWithSubnetFromGwPort.getIpAddress()), subnetId,
+ Collections.singletonList(
+ new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build()));
+ } else {
+ subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, subnetId, Collections.singletonList(
+ new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build()));
+ }
+ rwTx.merge(LogicalDatastoreType.CONFIGURATION,
+ L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
ContextId l2BdId = new ContextId(potentialSubnet.get().getNetworkId().getValue());
Optional<ForwardingContext> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
rwTx.cancel();
return;
}
- ForwardingContext l2BdWithGw = new ForwardingContextBuilder(optBd.get())
- .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT))
- .build();
+ ForwardingContext forwardingContext = optBd.get();
+ ForwardingContext l2BdWithGw = new ForwardingContextBuilder(forwardingContext)
+ .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT))
+ .build();
rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
l2BdWithGw);
}
DataStoreHelper.submitToDs(rwTx);
}
+ private boolean isSubnetInExternalNetwork(List<Network> networks, Uuid networkId) {
+ return networks.stream().anyMatch(net -> net.getUuid().equals(networkId) && NetworkUtils.isRouterExternal(net));
+ }
+
private boolean registerExternalGateway(TenantId tenantId, IpPrefix ipPrefix, ContextId routerl3ContextId,
NetworkDomainId networkDomainId) {
AddressEndpointRegBuilder addrEpBuilder = new AddressEndpointRegBuilder();
return epRegistrator.unregisterEndpoint(addrEpBuilder.build());
}
- private NetworkDomain createSubnetWithVirtualRouterIp(IpPrefix gatewayIp, NetworkDomainId subnetId) {
- Subnet subnet = new SubnetBuilder().setVirtualRouterIp(MappingUtils.ipPrefixToIpAddress(gatewayIp.getValue())).build();
+private NetworkDomain createSubnetWithVirtualRouterIp(IpPrefix gatewayIp, NetworkDomainId subnetId, List<Gateways> gateways) {
+ Subnet subnet = new SubnetBuilder()
+ .setVirtualRouterIp(MappingUtils.ipPrefixToIpAddress(gatewayIp.getValue()))
+ .setGateways(gateways)
+ .build();
return new NetworkDomainBuilder().setKey(new NetworkDomainKey(subnetId, MappingUtils.SUBNET))
.addAugmentation(SubnetAugmentForwarding.class,
new SubnetAugmentForwardingBuilder().setSubnet(subnet).build())
InstanceIdentifier<L3Context> l3ContextIid =
IidFactory.l3ContextIid(tenantId, l3ContextId);
Optional<L3Context> optL3Context = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l3ContextIid, rwTx);
- L3Context l3Context = null;
- if (optL3Context.isPresent()) {
- l3Context = optL3Context.get();
- } else { // add L3 context if missing
- l3Context = createL3CtxFromRouter(newRouter);
- rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true);
- }
+ L3Context l3Context;
+ if (!optL3Context.isPresent()) { // add L3 context if missing
+ l3Context = createL3CtxFromRouter(newRouter);
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true);
+ }
- if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
+ if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
// external network is attached to router
Uuid gatewayPortId = newRouter.getGatewayPortId();
Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts());
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet
subnet =
new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder(
- subnetOptional.get()).setVirtualRouterIp(null).build();
+ subnetOptional.get()).setVirtualRouterIp(null).setGateways(null).build();
LOG.trace("Removing VirtualRouterIp from subnet {}.", subnetOptional.get());
rwTx.put(LogicalDatastoreType.CONFIGURATION,
IidFactory.subnetIid(tenantId, new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue())), subnet);
Subnet originalSubnet = domainOptional.get().getAugmentation(SubnetAugmentForwarding.class).getSubnet();
if (originalSubnet != null) {
LOG.trace("Deleting virtual router IP from Subnet {} in gateway {}", originalSubnet, gatewayPortId);
- SubnetBuilder subnetBuilder = new SubnetBuilder(originalSubnet).setVirtualRouterIp(null);
+ SubnetBuilder subnetBuilder = new SubnetBuilder(originalSubnet).setVirtualRouterIp(null)
+ .setGateways(null);
rwTx.put(LogicalDatastoreType.CONFIGURATION,
L2L3IidFactory.subnetIid(tenantId, domainId)
.augmentation(SubnetAugmentForwarding.class)
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
import org.opendaylight.groupbasedpolicy.util.IidFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
public static final InstanceIdentifier<SecurityGroup> SECURITY_GROUP_WILDCARD_IID =
InstanceIdentifier.builder(Neutron.class).child(SecurityGroups.class).child(SecurityGroup.class).build();
private final DataBroker dataProvider;
+ private final NeutronSecurityRuleAware ruleAware;
- public NeutronSecurityGroupAware(DataBroker dataProvider) {
+ public NeutronSecurityGroupAware(DataBroker dataProvider, NeutronSecurityRuleAware ruleAware) {
this.dataProvider = checkNotNull(dataProvider);
+ this.ruleAware = checkNotNull(ruleAware);
}
@Override
} else {
rwTx.cancel();
}
+ ruleAware.flushPendingSecurityRulesFor(createdSecGroup.getKey(), neutron);
}
public boolean addNeutronSecurityGroup(SecurityGroup secGroup, ReadWriteTransaction rwTx) {
@Override
public void onDeleted(SecurityGroup deletedSecGroup, Neutron oldNeutron, Neutron newNeutron) {
LOG.trace("deleted securityGroup - {}", deletedSecGroup);
- ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
- TenantId tenantId = new TenantId(deletedSecGroup.getTenantId().getValue());
- EndpointGroupId epgId = new EndpointGroupId(deletedSecGroup.getUuid().getValue());
+ if (newNeutron != null && newNeutron.getSecurityRules() != null
+ && newNeutron.getSecurityRules().getSecurityRule() != null
+ && newNeutron.getSecurityRules()
+ .getSecurityRule()
+ .stream()
+ .filter(sr -> sr.getSecurityGroupId().equals(deletedSecGroup.getUuid()))
+ .findAny()
+ .isPresent()) {
+ LOG.warn("Cannot remove security group {} before removing last security rule.", deletedSecGroup.getKey());
+ ruleAware.addPendingDeletedSecGroup(deletedSecGroup);
+ return;
+ }
+ deleteGbpEndpointGroup(dataProvider, new TenantId(deletedSecGroup.getTenantId().getValue()),
+ new EndpointGroupId(deletedSecGroup.getUuid().getValue()));
+ }
+
+ public static void deleteGbpEndpointGroup(DataBroker dataBroker, TenantId tenantId, EndpointGroupId epgId) {
+ ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
Optional<EndpointGroup> potentialEpg = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
if (!potentialEpg.isPresent()) {
rwTx.cancel();
return;
}
-
DataStoreHelper.submitToDs(rwTx);
}
-
}
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.Collections;
import java.util.List;
+import java.util.function.Function;
import java.util.stream.Collectors;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPool;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.PrefixesBuilder;
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.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.AllocationPools;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
Network networkOfSubnet = potentialNetwork.get();
- NetworkDomain subnetDomain = null;
+ NetworkDomain subnetDomain;
+ IpAddress gatewayIp = neutronSubnet.getGatewayIp();
if (NetworkUtils.isProviderPhysicalNetwork(networkOfSubnet)) {
- subnetDomain = createSubnet(neutronSubnet, neutron);
- IpAddress gatewayIp = neutronSubnet.getGatewayIp();
+ // add virtual router IP only in case it is provider physical network
+ subnetDomain = createSubnet(neutronSubnet, neutron, gatewayIp);
boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE,
new L3ContextId(neutronSubnet.getNetworkId().getValue()), gatewayIp, tenantId);
if (!registeredDefaultRoute) {
LOG.warn("Could not add EndpointL3Prefix as default route. Subnet within provider physical network {}",
- neutronSubnet);
+ neutronSubnet);
rwTx.cancel();
return;
}
} else {
- subnetDomain = createSubnet(neutronSubnet, neutron);
+ // virtual router IP is not set and it will be set when router gateway port is set
+ // or when a router port is attached to a network
+ if (NetworkUtils.isRouterExternal(networkOfSubnet)) {
+ subnetDomain = createSubnet(neutronSubnet, neutron, gatewayIp);
+ } else {
+ subnetDomain = createSubnet(neutronSubnet, neutron, null);
+ }
}
processTenantSubnet(neutronSubnet, networkOfSubnet, tenantId, rwTx);
- rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true);
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true);
DataStoreHelper.submitToDs(rwTx);
}
public static NetworkDomain createSubnet(
org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet,
- Neutron neutron) {
+ Neutron neutron, IpAddress gwIpAddress) {
SubnetBuilder sb = new SubnetBuilder();
sb.setIpPrefix(subnet.getCidr());
+ if (gwIpAddress != null) {
+ sb.setGateways(Collections.singletonList(new GatewaysBuilder().setGateway(gwIpAddress)
+ .setPrefixes(
+ Collections.singletonList(new PrefixesBuilder().setPrefix(MappingUtils.DEFAULT_ROUTE).build()))
+ .build()));
+ }
if (neutron.getPorts() != null && neutron.getPorts().getPort() != null) {
for (Port port : neutron.getPorts().getPort()) {
if (port.getFixedIps() == null || !port.getFixedIps()
sb.setIsTenant(NetworkUtils.isTenantNetwork(potentialNetwork.get()));
}
if (subnet.getAllocationPools() != null) {
- List<AllocationPool> pools = subnet.getAllocationPools()
- .stream()
- .map(s -> new AllocationPoolBuilder().setFirst(s.getStart().getIpv4Address().getValue())
- .setLast(s.getEnd().getIpv4Address().getValue())
- .build())
- .collect(Collectors.toList());
+ List<AllocationPool> pools =
+ subnet.getAllocationPools().stream().map(new Function<AllocationPools, AllocationPool>() {
+
+ @Override
+ public AllocationPool apply(AllocationPools ap) {
+ IpAddress start = ap.getStart();
+ IpAddress end = ap.getEnd();
+ AllocationPoolBuilder ab = new AllocationPoolBuilder();
+ if (start.getIpv4Address() != null || end.getIpv4Address() != null) {
+ ab.setFirst(start.getIpv4Address().getValue());
+ ab.setLast(end.getIpv4Address().getValue());
+ } else {
+ ab.setFirst(start.getIpv6Address().getValue());
+ ab.setLast(end.getIpv6Address().getValue());
+ }
+ return ab.build();
+ }
+ }).collect(Collectors.toList());
sb.setAllocationPool(pools);
}
NetworkDomainBuilder ndb = new NetworkDomainBuilder();
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
import org.opendaylight.controller.config.yang.config.neutron_mapper.impl.NeutronMapperModule;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronAware;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityGroupUtils;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityRuleUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroupKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multiset;
private final DataBroker dataProvider;
private final Multiset<InstanceIdentifier<ClassifierInstance>> createdClassifierInstances;
private final Multiset<InstanceIdentifier<ActionInstance>> createdActionInstances;
+ private final Map<SecurityRuleKey, SecurityRule> pendingCreatedRules;
+ private final Map<SecurityGroupKey, SecurityGroup> pendingDeletedGroups;
final static String PROVIDED_BY = "provided_by-";
final static String POSSIBLE_CONSUMER = "possible_consumer-";
this.dataProvider = checkNotNull(dataProvider);
this.createdClassifierInstances = checkNotNull(classifierInstanceNames);
this.createdActionInstances = checkNotNull(createdActionInstances);
+ this.pendingCreatedRules = new HashMap<>();
+ this.pendingDeletedGroups = new HashMap<>();
}
@Override
public void onCreated(SecurityRule secRule, Neutron neutron) {
LOG.trace("created securityRule - {}", secRule);
+ if (neutron.getSecurityGroups() == null || neutron.getSecurityGroups().getSecurityGroup() == null
+ || !neutron.getSecurityGroups()
+ .getSecurityGroup()
+ .stream()
+ .filter(sg -> sg.getKey().getUuid().equals(secRule.getSecurityGroupId()))
+ .findFirst()
+ .isPresent()) {
+ pendingCreatedRules.put(secRule.getKey(), secRule);
+ LOG.warn("Security group of security rule {} does not exist yet. The rule will be processed"
+ + "when the missing security group is created.", secRule.getKey());
+ return;
+ }
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(secRule, neutron, rwTx);
if (isNeutronSecurityRuleAdded) {
}
}
+ public void flushPendingSecurityRulesFor(@Nonnull SecurityGroupKey secGroupKey, Neutron neutron) {
+ List<SecurityRule> rules = pendingCreatedRules.values()
+ .stream()
+ .filter(sr -> sr.getSecurityGroupId().equals(secGroupKey.getUuid()))
+ .collect(Collectors.toList());
+ rules.forEach(sr -> {
+ LOG.trace("Flushing pending security rule {}", sr);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(sr, neutron, rwTx);
+ if (isNeutronSecurityRuleAdded) {
+ DataStoreHelper.submitToDs(rwTx);
+ } else {
+ rwTx.cancel();
+ }
+ pendingCreatedRules.remove(sr.getKey());
+ });
+ }
+
public boolean addNeutronSecurityRule(SecurityRule secRule, Neutron neutron, ReadWriteTransaction rwTx) {
return addNeutronSecurityRuleWithAction(secRule, neutron, MappingUtils.ALLOW_ACTION_CHOICE, rwTx);
}
newSecRule);
}
+ public void addPendingDeletedSecGroup(SecurityGroup secGroup) {
+ LOG.trace("Caching pending deleted security group {}", secGroup.getKey());
+ pendingDeletedGroups.put(secGroup.getKey(), secGroup);
+ }
+
@Override
public void onDeleted(SecurityRule deletedSecRule, Neutron oldNeutron, Neutron newNeutron) {
LOG.trace("deleted securityRule - {}", deletedSecRule);
boolean isNeutronSecurityRuleDeleted = deleteNeutronSecurityRule(deletedSecRule, oldNeutron, rwTx);
if (isNeutronSecurityRuleDeleted) {
DataStoreHelper.submitToDs(rwTx);
+ if (newNeutron == null || newNeutron.getSecurityRules() == null
+ || newNeutron.getSecurityRules().getSecurityRule() == null
+ || !newNeutron.getSecurityRules()
+ .getSecurityRule()
+ .stream()
+ .filter(rule -> rule.getSecurityGroupId().equals(deletedSecRule.getSecurityGroupId()))
+ .findAny()
+ .isPresent()) {
+ SecurityGroupKey secGroupKey = new SecurityGroupKey(deletedSecRule.getSecurityGroupId());
+ SecurityGroup pendingSg = pendingDeletedGroups.get(secGroupKey);
+ if (pendingSg != null) {
+ LOG.trace("Processing pending deleted security group {}", secGroupKey);
+ NeutronSecurityGroupAware.deleteGbpEndpointGroup(dataProvider,
+ new TenantId(deletedSecRule.getTenantId().getValue()),
+ new EndpointGroupId(secGroupKey.getUuid().getValue()));
+ pendingDeletedGroups.remove(secGroupKey);
+ }
+ }
} else {
rwTx.cancel();
}
.setFixedIps(ImmutableList.of(portIpWithSubnet))
.build();
portAware.onCreated(port, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron, ipAddress);
portAware.onDeleted(port, neutron, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron, ipAddress);
NeutronMapperAssert.assertPortNotExists(dataBroker, port.getUuid());
}
@Test
public void test_createRouterInterfacePort_noFixedIps() {
- IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
Subnets subnets = createSubnets();
when(neutron.getSubnets()).thenReturn(subnets);
Subnet subnet = subnets.getSubnet().get(0);
Port port = newBasePort().setDeviceOwner(PortUtils.DEVICE_OWNER_ROUTER_IFACE).build();
portAware.onCreated(port, neutron);
- NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, port, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, port, subnet, neutron, null);
}
@Test
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.NetworksBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
public void testOnUpdated() {
Subnets subnets = createSubnets();
when(neutron.getSubnets()).thenReturn(subnets);
+ when(neutron.getNetworks()).thenReturn(new NetworksBuilder().setNetwork(ImmutableList.of(network)).build());
FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
public void testOnUpdated_noL2BridgeDomain() {
Subnets subnets = createSubnets();
when(neutron.getSubnets()).thenReturn(subnets);
+ when(neutron.getNetworks()).thenReturn(new NetworksBuilder().setNetwork(ImmutableList.of(network)).build());
FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
import org.junit.rules.ExpectedException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronEntityFactory;
import org.opendaylight.groupbasedpolicy.neutron.mapper.test.PolicyAssert;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
@Before
public void init() {
dataBroker = getDataBroker();
- groupAware = new NeutronSecurityGroupAware(dataBroker);
+ groupAware = new NeutronSecurityGroupAware(dataBroker, new NeutronSecurityRuleAware(dataBroker));
secGroup1 = NeutronEntityFactory.securityGroup(secGroupId1, tenantId);
secGroup2 = NeutronEntityFactory.securityGroup(secGroupId2, tenantId);
@Test
public void testConstructor_invalidArgument() throws NullPointerException {
thrown.expect(NullPointerException.class);
- new NeutronSecurityGroupAware(null);
+ new NeutronSecurityGroupAware(null, null);
}
@Test
subnetAware.onCreated(subnet, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
}
@Test
subnetAware.onCreated(subnet, neutron);
- NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron, null);
}
@Test
subnetAware.onCreated(subnet, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
- NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet2, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
+ NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet2, neutron, null);
subnetAware.onUpdated(subnet, subnet2, neutron, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet2, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet2, neutron, null);
}
@Test
subnetAware.onCreated(subnet, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
subnetAware.onDeleted(subnet, neutron, neutron);
- NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron, null);
}
@Test
public void testOnDeleted_wrongSubnet() {
subnetAware.onCreated(subnet, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
subnetAware.onDeleted(subnet2, neutron, neutron);
- NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+ NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
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.endpoints.by.ports.EndpointByPort;
-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.ports.attributes.ports.Port;
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.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public class NeutronMapperAssert {
return portOptional;
}
- public static void assertNetworkDomainExists(DataBroker dataBroker, Port port, Subnet subnet, Neutron neutron) {
+ public static void assertNetworkDomainExists(DataBroker dataBroker, Port port, Subnet subnet, Neutron neutron,
+ IpAddress ipAddress) {
Optional<NetworkDomain> opt =
- getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, subnet);
+ getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, ipAddress, subnet);
assertTrue(opt.isPresent());
}
public static void assertNetworkDomainNotExists(DataBroker dataBroker, Port port, Subnet subnet,
- Neutron neutron) {
+ Neutron neutron, IpAddress ipAddress) {
Optional<NetworkDomain> opt =
- getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, subnet);
+ getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, ipAddress, subnet);
assertFalse(opt.isPresent());
}
public static void assertNetworkDomainExists(DataBroker dataBroker, Uuid tenantUuid, Subnet subnet,
- Neutron neutron) {
- Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, subnet);
+ Neutron neutron, IpAddress ipAddress) {
+ Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, ipAddress, subnet);
assertTrue(opt.isPresent());
}
public static void assertNetworkDomainNotExists(DataBroker dataBroker, Uuid tenantUuid, Subnet subnet,
- Neutron neutron) {
- Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, subnet);
+ Neutron neutron, IpAddress ipAddress) {
+ Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, ipAddress, subnet);
assertFalse(opt.isPresent());
}
private static Optional<NetworkDomain> getNetworkDomainOptional(DataBroker dataBroker, Uuid tenantUuid,
- Neutron neutron, Subnet subnet) {
+ Neutron neutron, IpAddress ipAddress, Subnet subnet) {
InstanceIdentifier<NetworkDomain> iid;
- NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(subnet, neutron);
+ NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(subnet, neutron, ipAddress);
TenantId tenantId = new TenantId(tenantUuid.getValue());
iid = L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId());
Optional<NetworkDomain> optional;
if (Strings.isNullOrEmpty(port.getDeviceId())) {\r
return Optional.absent();\r
}\r
+ RouterKey routerKey = null;\r
+ try {\r
+ routerKey = new RouterKey(new Uuid(port.getDeviceId()));\r
+ } catch (IllegalArgumentException e) {\r
+ // port.getDeviceId() may not match Uuid.PATTERN_CONSTANTS\r
+ return Optional.absent();\r
+ }\r
ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();\r
InstanceIdentifier<Router> routerIid = InstanceIdentifier.builder(Neutron.class)\r
.child(Routers.class)\r
- .child(Router.class, new RouterKey(new Uuid(port.getDeviceId())))\r
+ .child(Router.class, routerKey)\r
.build();\r
Optional<Router> optRouter = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, routerIid, rTx);\r
rTx.close();\r
private final ClusterSingletonServiceProvider clusterSingletonService;
private ClusterSingletonServiceRegistration singletonServiceRegistration;
private VppRenderer renderer;
+ private final String publicInterfaces;
public GbpVppProviderInstance(final DataBroker dataBroker,
final BindingAwareBroker bindingAwareBroker,
- final ClusterSingletonServiceProvider clusterSingletonService) {
+ final ClusterSingletonServiceProvider clusterSingletonService,
+ final String publicInterfaces) {
this.dataBroker = Preconditions.checkNotNull(dataBroker);
this.bindingAwareBroker = Preconditions.checkNotNull(bindingAwareBroker);
this.clusterSingletonService = Preconditions.checkNotNull(clusterSingletonService);
+ this.publicInterfaces = publicInterfaces;
}
public void initialize() {
@Override
public void instantiateServiceInstance() {
LOG.info("Instantiating {}", this.getClass().getSimpleName());
- renderer = new VppRenderer(dataBroker, bindingAwareBroker);
+ renderer = new VppRenderer(dataBroker, bindingAwareBroker, publicInterfaces);
}
@Override
import java.util.ArrayList;
import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.MountPointService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.adapter.VppRpcServiceImpl;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyListener;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.BridgeDomainManagerImpl;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.ForwardingManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.VppRendererPolicyManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.AllowAction;
import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier;
import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.EtherTypeClassifier;
private VppEndpointListener vppEndpointListener;
private RendererPolicyListener rendererPolicyListener;
private VppRpcServiceImpl vppRpcServiceImpl;
+ private final String publicInterfaces;
- public VppRenderer(DataBroker dataBroker, BindingAwareBroker bindingAwareBroker) {
+ public VppRenderer(@Nonnull DataBroker dataBroker, @Nonnull BindingAwareBroker bindingAwareBroker,
+ @Nullable String publicInterfaces) {
this.dataBroker = Preconditions.checkNotNull(dataBroker);
+ this.publicInterfaces = publicInterfaces;
bindingAwareBroker.registerProvider(this);
EtherTypeClassifier etherTypeClassifier = new EtherTypeClassifier(null);
IpProtoClassifier ipProtoClassifier = new IpProtoClassifier(etherTypeClassifier);
MountPointService mountService =
Preconditions.checkNotNull(providerContext.getSALService(MountPointService.class));
MountedDataBrokerProvider mountDataProvider = new MountedDataBrokerProvider(mountService, dataBroker);
- vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+ vppNodeManager = new VppNodeManager(dataBroker, providerContext, publicInterfaces);
EventBus dtoEventBus = new EventBus((exception, context) -> LOG.error("Could not dispatch event: {} to {}",
context.getSubscriber(), context.getSubscriberMethod(), exception));
aclManager = new AclManager(mountDataProvider);
NatManager natManager = new NatManager(dataBroker, mountDataProvider);
dtoEventBus.register(interfaceManager);
+ RoutingManager routingManager = new RoutingManager(dataBroker, mountDataProvider);
BridgeDomainManager bdManager = new BridgeDomainManagerImpl(dataBroker);
- ForwardingManager fwManager = new ForwardingManager(interfaceManager, aclManager, natManager, bdManager, dataBroker);
+ ForwardingManager fwManager =
+ new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bdManager, dataBroker);
vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
dtoEventBus.register(vppRendererPolicyManager);
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems. 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.renderer.vpp.commands;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Static;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol.StaticRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttr;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttrBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.routing.instance.routing.protocols.routing.protocol.VppProtocolAttributesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class RoutingCommand {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractInterfaceCommand.class);
+ public static String ROUTER_INSTANCE_NAME = "vpp-routing-instance";
+ private General.Operations operation;
+ private String routerProtocol;
+ private Long vrfId;
+ private List<Route> routes;
+
+ public String getRouterProtocol() {
+ return routerProtocol;
+ }
+
+ public Long getVrfId() {
+ return vrfId;
+ }
+
+ public List<Route> getRoutes() {
+ return routes;
+ }
+
+ private RoutingCommand(RoutingCommandBuilder builder) {
+ operation = builder.getOperation();
+ routerProtocol = builder.getRouterProtocol();
+ vrfId = builder.getVrfId();
+ routes = builder.getRoutes();
+ }
+
+ public static RoutingCommandBuilder builder() {
+ return new RoutingCommandBuilder();
+ }
+
+ public General.Operations getOperation() {
+ return operation;
+ }
+
+ public RoutingProtocolBuilder getRoutingProtocolBuilder() {
+ return new RoutingProtocolBuilder()
+ .setEnabled(true)
+ .setType(Static.class)
+ .setName(routerProtocol)
+ .addAugmentation(RoutingProtocolVppAttr.class, new RoutingProtocolVppAttrBuilder().setVppProtocolAttributes(
+ new VppProtocolAttributesBuilder().setPrimaryVrf(new VniReference(vrfId)).build()).build())
+ .setStaticRoutes(new StaticRoutesBuilder().addAugmentation(StaticRoutes1.class,
+ new StaticRoutes1Builder().setIpv4(new Ipv4Builder().setRoute(routes).build()).build()).build());
+ }
+
+ public void execute(ReadWriteTransaction rwTx) {
+ switch (getOperation()) {
+ case PUT:
+ LOG.debug("Executing Add operations for routing command: {}", this);
+ put(rwTx);
+ break;
+ case DELETE:
+ LOG.debug("Executing Delete operations for routing command: {}", this);
+ delete(rwTx);
+ break;
+ case MERGE:
+ LOG.debug("Executing Merge operations for routing command: {}", this);
+ merge(rwTx);
+ break;
+ default:
+ LOG.error("Execution failed for routing command: {}", this);
+ break;
+ }
+ }
+
+ private void merge(ReadWriteTransaction rwTx) {
+ rwTx.merge(LogicalDatastoreType.CONFIGURATION,
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol)),
+ getRoutingProtocolBuilder().build(), true);
+ }
+
+ private void delete(ReadWriteTransaction rwTx) {
+ try {
+ rwTx.delete(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(
+ routerProtocol)));
+ } catch (IllegalStateException ex) {
+ LOG.debug("Routing protocol not deleted from DS {}", this, ex);
+ }
+ }
+
+ private void put(ReadWriteTransaction rwTx) {
+ InstanceIdentifier<RoutingProtocol> routingInstanceIid =
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol));
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, routingInstanceIid, getRoutingProtocolBuilder().build(), true);
+ }
+
+ @Override public String toString() {
+ return "RoutingCommand [routerProtocol=" + routerProtocol + ", routes=" + routes + ", operations="
+ + operation + "]";
+ }
+
+ public static class RoutingCommandBuilder {
+
+ private General.Operations operation;
+ private String routerProtocol;
+ private Long vrfId;
+ private List<Route> routes;
+
+ public General.Operations getOperation() {
+ return operation;
+ }
+
+ public RoutingCommandBuilder setOperation(General.Operations operation) {
+ this.operation = operation;
+ return this;
+ }
+
+ public String getRouterProtocol() {
+ return routerProtocol;
+ }
+
+ public RoutingCommandBuilder setRouterProtocol(String routerProtocol) {
+ this.routerProtocol = routerProtocol;
+ return this;
+ }
+
+ public Long getVrfId() {
+ return vrfId;
+ }
+
+ public RoutingCommandBuilder setVrfId(Long vrfId) {
+ this.vrfId = vrfId;
+ return this;
+ }
+
+ public List<Route> getRoutes() {
+ return routes;
+ }
+
+ public RoutingCommandBuilder setRoutes(List<Route> routes) {
+ this.routes = routes;
+ return this;
+ }
+
+ /**
+ * RoutingCommand build method.
+ *
+ * @return RoutingCommand
+ * @throws IllegalArgumentException if routerProtocol, operation or vrfId is null.
+ */
+ public RoutingCommand build() {
+ Preconditions.checkArgument(this.operation != null);
+ Preconditions.checkArgument(this.routerProtocol != null);
+ Preconditions.checkArgument(this.vrfId != null);
+ return new RoutingCommand(this);
+ }
+ }
+}
public void updateAclsForRendEp(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
LOG.info("Updating policy for endpoint {}", rEpKey);
AddressEndpointWithLocation peerAddrEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
- ExternalLocationCase epLoc = InterfaceManager.resolveAndValidateLocation(peerAddrEp);
+ ExternalLocationCase epLoc;
+ try {
+ epLoc = InterfaceManager.resolveAndValidateLocation(peerAddrEp);
+ } catch (NullPointerException | IllegalArgumentException e) {
+ //TODO investigate, don't just move on.
+ LOG.warn("Peer {} has no location. Moving on...", peerAddrEp, e.getMessage());
+ return;
+ }
InstanceIdentifier<?> vppNodeIid = epLoc.getExternalNodeMountPoint();
Optional<InstanceIdentifier<Interface>> optInterfaceIid =
VppPathMapper.interfaceToInstanceIdentifier(epLoc.getExternalNodeConnector());
import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected;
import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
-import java.util.concurrent.*;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.stream.Collectors;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.MountPoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentationBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
public class VppNodeManager {
private static final short DURATION = 3000;
private static final String V3PO_CAPABILITY = "(urn:opendaylight:params:xml:ns:yang:v3po?revision=2016-12-14)v3po";
private static final String INTERFACES_CAPABILITY = "(urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08)ietf-interfaces";
private static final NodeId CONTROLLER_CONFIG_NODE = new NodeId("controller-config");
+ private static final String NO_PUBLIC_INT_SPECIFIED = "unspecified";
+ private final Map<NodeId, PhysicalInterfaceKey> extInterfaces = new HashMap<>();
private final DataBroker dataBroker;
private final List<String> requiredCapabilities;
private final MountPointService mountService;
- public VppNodeManager(final DataBroker dataBroker, final BindingAwareBroker.ProviderContext session) {
+ public VppNodeManager(@Nonnull final DataBroker dataBroker,
+ @Nonnull final BindingAwareBroker.ProviderContext session, @Nullable String physicalInterfaces) {
this.dataBroker = Preconditions.checkNotNull(dataBroker);
this.mountService = Preconditions.checkNotNull(session.getSALService(MountPointService.class));
requiredCapabilities = initializeRequiredCapabilities();
+ if (!Strings.isNullOrEmpty(physicalInterfaces) && physicalInterfaces != NO_PUBLIC_INT_SPECIFIED) {
+ loadPhysicalInterfaces(physicalInterfaces);
+ }
+ }
+
+ /**
+ * Caches list of physical interfaces.
+ */
+ public void loadPhysicalInterfaces(@Nonnull String physicalInterfaces) {
+ for (String intfOnNode : Sets.newConcurrentHashSet(Splitter.on(",").split(physicalInterfaces))) {
+ List<String> entries = Lists.newArrayList(Splitter.on(":").split(intfOnNode));
+ if (entries.size() != 2) {
+ LOG.warn("Cannot resolve {} initial configuration for physical interfaces.", intfOnNode);
+ continue;
+ }
+ NodeId nodeId = new NodeId(entries.get(0));
+ PhysicalInterfaceKey infaceKey = new PhysicalInterfaceKey(entries.get(1));
+ LOG.info("Interface " + infaceKey + " on node " + nodeId + "will be considered as external");
+ extInterfaces.put(nodeId, infaceKey);
+ }
}
/**
private void syncPhysicalInterfacesInLocalDs(DataBroker mountPointDataBroker, InstanceIdentifier<Node> nodeIid) {
ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
- InstanceIdentifier.create(Interfaces.class);
ReadOnlyTransaction rTx = mountPointDataBroker.newReadOnlyTransaction();
Optional<Interfaces> readIfaces = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
InstanceIdentifier.create(Interfaces.class), rTx);
.build();
Optional<RendererNode> optRendNode = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
rendererNodeIid, rwTx);
- RendererNode rendNode = new RendererNodeBuilder(optRendNode.get()).addAugmentation(
- VppInterfaceAugmentation.class, resolveTerminationPoints(readIfaces.get())).build();
+ NodeId nodeId = nodeIid.firstKeyOf(Node.class).getNodeId();
+ RendererNode rendNode = new RendererNodeBuilder(optRendNode.get())
+ .addAugmentation(VppInterfaceAugmentation.class, resolveTerminationPoints(nodeId, readIfaces.get()))
+ .build();
rwTx.put(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererNodeIid(optRendNode.get()), rendNode,
true);
}
DataStoreHelper.submitToDs(rwTx);
}
- private VppInterfaceAugmentation resolveTerminationPoints(Interfaces interfaces) {
+ private VppInterfaceAugmentation resolveTerminationPoints(NodeId nodeId, Interfaces interfaces) {
List<PhysicalInterface> phIfaces = new ArrayList<>();
- PhysicalInterfaceBuilder phIface = new PhysicalInterfaceBuilder();
if (interfaces != null && interfaces.getInterface() != null) {
interfaces.getInterface()
.stream()
.filter(iface -> iface.getType().equals(EthernetCsmacd.class))
.filter(iface -> iface.getAugmentation(Interface1.class) != null)
.forEach(iface -> {
+ PhysicalInterfaceBuilder phIface = new PhysicalInterfaceBuilder();
phIface.setInterfaceName(iface.getName());
phIface.setType(iface.getType());
phIface.setAddress(resolveIpAddress(iface.getAugmentation(Interface1.class)));
+
+ if (extInterfaces.get(nodeId) != null && extInterfaces.get(nodeId)
+ .getInterfaceName()
+ .equals(phIface.getInterfaceName())) {
+ phIface.setExternal(true);
+ LOG.trace("Assigning external Interface, interface name: {}, extInterface name: {}",
+ phIface.getInterfaceName(), extInterfaces.get(nodeId).getInterfaceName());
+ }
phIfaces.add(phIface.build());
});
}
import java.net.Inet6Address;\r
import java.net.InetAddress;\r
import java.net.UnknownHostException;\r
-import java.util.ArrayList;\r
import java.util.List;\r
-import java.util.concurrent.ExecutionException;\r
import java.util.concurrent.atomic.AtomicInteger;\r
import java.util.stream.Collectors;\r
\r
+import org.apache.commons.net.util.SubnetUtils;\r
import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;\r
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;\r
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
-import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
-import org.opendaylight.groupbasedpolicy.util.NetUtils;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentation;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;\r
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
\r
import com.google.common.base.Optional;\r
-import com.google.common.util.concurrent.AsyncFunction;\r
-import com.google.common.util.concurrent.Futures;\r
-import com.google.common.util.concurrent.ListenableFuture;\r
-\r
public class NatManager {\r
\r
private static final Logger LOG = LoggerFactory.getLogger(NatManager.class);\r
this.mountDataProvider = mountDataProvider;\r
}\r
\r
- public Optional<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix) {\r
- ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
- Optional<RendererNodes> readFromDs = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,\r
- VppIidFactory.getRendererNodesIid(), rTx);\r
- rTx.close();\r
- if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
- return Optional.absent();\r
- }\r
- RendererNodes rendererNodes = readFromDs.get();\r
- List<RendererNode> vppNodes = rendererNodes.getRendererNode()\r
- .stream()\r
- .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class) != null)\r
- .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class).getPhysicalInterface() != null)\r
- .collect(Collectors.toList());\r
- for (RendererNode rn : vppNodes) {\r
- java.util.Optional<PhysicalInterface> optResolvedIface = rn.getAugmentation(VppInterfaceAugmentation.class)\r
- .getPhysicalInterface()\r
- .stream()\r
- .filter(phIface -> phIface.getAddress() != null)\r
- .filter(phIface -> phIface.getAddress()\r
- .stream()\r
- .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))\r
- .findFirst();\r
- if (optResolvedIface.isPresent()) {\r
- return Optional.of(VppIidFactory.getRendererNodeIid(rn)\r
- .builder()\r
- .augmentation(VppInterfaceAugmentation.class)\r
- .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))\r
- .build());\r
- }\r
- }\r
- return Optional.absent();\r
- }\r
-\r
public Optional<MappingEntryBuilder> resolveSnatEntry(String internal, Ipv4Address external) {\r
IpAddress internalIp = null;\r
+ LOG.trace("Resolving SNAT entry for internal: {}, external: {}", internal, external);\r
try {\r
InetAddress inetAddr = InetAddress.getByName(internal);\r
if (inetAddr instanceof Inet4Address) {\r
LOG.error("Cannot resolve host IP {}. {}", internal, e.getMessage());\r
return Optional.absent();\r
}\r
- return Optional.of(new MappingEntryBuilder().setInternalSrcAddress(internalIp).setExternalSrcAddress(external));\r
+ SubnetUtils subnet = new SubnetUtils(internal + "/32" );\r
+ Long index = Integer.toUnsignedLong(subnet.getInfo().asInteger(internal));\r
+ MappingEntryBuilder mappingEntryBuilder =\r
+ new MappingEntryBuilder().setType(\r
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static)\r
+ .setIndex(index)\r
+ .setInternalSrcAddress(internalIp)\r
+ .setExternalSrcAddress(external);\r
+ LOG.trace("Resolved SNAT mapping: {}", mappingEntryBuilder.build().toString());\r
+ return Optional.of(mappingEntryBuilder);\r
}\r
\r
- public ListenableFuture<Void> submitNatChanges(List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
+ public void submitNatChanges(List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
List<MappingEntryBuilder> natEntries, PolicyContext policyCtx, boolean add) {\r
- List<ListenableFuture<Void>> submitedFutures = new ArrayList<>();\r
+ LOG.trace("Preparing to submit NAT changes {} on physical interfaces", natEntries.toArray(), physIfacesIid);\r
for (InstanceIdentifier<PhysicalInterface> iidPhysIface : physIfacesIid) {\r
InstanceIdentifier<?> nodeIid = iidPhysIface.firstKeyOf(RendererNode.class).getNodePath();\r
Optional<DataBroker> mountPointDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid);\r
throw new IllegalStateException("Cannot find data broker for mount point " + nodeIid);\r
}\r
String phInterfaceName = iidPhysIface.firstKeyOf(PhysicalInterface.class).getInterfaceName();\r
- ReadWriteTransaction rwTx = mountPointDataBroker.get().newReadWriteTransaction();\r
- InstanceIdentifier<Interface> interfaceIID = VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
- submitedFutures.add(Futures.transform(rwTx.read(LogicalDatastoreType.CONFIGURATION, interfaceIID),\r
- new AsyncFunction<Optional<Interface>, Void>() {\r
+ InstanceIdentifier<Interface> interfaceIID =\r
+ VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
\r
- @Override\r
- public ListenableFuture<Void> apply(Optional<Interface> readIface) throws Exception {\r
- if (!readIface.isPresent()) {\r
- LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
- return Futures.immediateFuture(null);\r
- }\r
- if (add) {\r
- LOG.trace("Setting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
- NatUtil.setOutboundInterface(readIface.get(), rwTx); \r
- rwTx.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id),\r
- buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx)));\r
- } else {\r
- LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
- NatUtil.unsetOutboundInterface(readIface.get(), rwTx);\r
- if (rwTx.read(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id))\r
- .get()\r
- .isPresent()) {\r
- rwTx.delete(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id));\r
- }\r
- }\r
- return rwTx.submit();\r
- }\r
- }));\r
- }\r
- try {\r
- Futures.allAsList(submitedFutures).get();\r
- } catch (InterruptedException | ExecutionException e) {\r
- LOG.error("Failed to sync NAT. {}", e.getMessage());\r
- e.printStackTrace();\r
+ Optional<Interface> readIface =\r
+ GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION, interfaceIID,\r
+ GbpNetconfTransaction.RETRY_COUNT);\r
+\r
+ if (!readIface.isPresent()) {\r
+ LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
+ return;\r
+ }\r
+ if (add) {\r
+ LOG.trace("Setting outbound NAT on interface {} on node: {}", iidPhysIface.getPathArguments(), nodeIid);\r
+ NatUtil.setOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
+ NatInstance natInstance =\r
+ buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx, natEntries));\r
+ GbpNetconfTransaction.netconfSyncedWrite(mountPointDataBroker.get(),\r
+ VppIidFactory.getNatInstanceIid(id), natInstance, GbpNetconfTransaction.RETRY_COUNT);\r
+ } else {\r
+ LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
+ NatUtil.unsetOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
+ if (GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT).isPresent()) {\r
+ GbpNetconfTransaction.netconfSyncedDelete(mountPointDataBroker.get(),\r
+ VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT);\r
+ }\r
+ }\r
+ return;\r
}\r
- return Futures.immediateFuture(null);\r
}\r
\r
- private NatInstance buildNatInstance(List<MappingEntryBuilder> natEntries, List<ExternalIpAddressPool> poolEntries) {\r
+ private NatInstance buildNatInstance(List<MappingEntryBuilder> natEntries,\r
+ List<ExternalIpAddressPool> poolEntries) {\r
AtomicInteger ai = new AtomicInteger();\r
List<MappingEntry> mappingEntries = natEntries.stream().map(me -> {\r
int value = ai.get();\r
return me.setIndex((long) value).build();\r
}).collect(Collectors.toList());\r
MappingTable mappingTable = new MappingTableBuilder().setMappingEntry(mappingEntries).build();\r
- return new NatInstanceBuilder().setId(id).setExternalIpAddressPool(poolEntries).setMappingTable(mappingTable).build();\r
+ return new NatInstanceBuilder()\r
+ .setId(id)\r
+ .setExternalIpAddressPool(poolEntries)\r
+ .setMappingTable(mappingTable)\r
+ .build();\r
}\r
}\r
/*\r
* Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
- * \r
+ *\r
* This program and the accompanying materials are made available under the\r
* terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
* and is available at http://www.eclipse.org/legal/epl-v10.html\r
\r
import java.util.ArrayList;\r
import java.util.HashMap;\r
+\r
+import com.google.common.annotations.VisibleForTesting;\r
+import com.google.common.base.Optional;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
import java.util.List;\r
import java.util.Map;\r
import java.util.Map.Entry;\r
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;\r
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;\r
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
+import org.opendaylight.groupbasedpolicy.util.NetUtils;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPool;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.RendererForwardingByTenant;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentation;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214.NatInterfaceAugmentation;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.Nat;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.InboundBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.OutboundBuilder;\r
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import java.util.stream.Collectors;\r
\r
public class NatUtil {\r
+ private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);\r
\r
public void setInboundInterface(Interface iface, WriteTransaction wTx) {\r
InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
wTx.put(LogicalDatastoreType.CONFIGURATION, natIid, nat);\r
}\r
\r
- public static void setOutboundInterface(Interface iface, WriteTransaction wTx) {\r
+ public static void setOutboundInterface(Interface iface, DataBroker dataBroker) {\r
InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
Nat nat = new NatBuilder().setOutbound(new OutboundBuilder().build()).build();\r
- wTx.put(LogicalDatastoreType.CONFIGURATION, natIid, nat);\r
+ GbpNetconfTransaction.netconfSyncedWrite(dataBroker, natIid, nat, GbpNetconfTransaction.RETRY_COUNT);\r
+\r
}\r
\r
- public static void unsetOutboundInterface(Interface iface, WriteTransaction wTx) {\r
+ public static void unsetOutboundInterface(Interface iface, DataBroker dataBroker) {\r
InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
- wTx.delete(LogicalDatastoreType.CONFIGURATION, natIid);\r
+ GbpNetconfTransaction.netconfSyncedDelete(dataBroker, natIid, GbpNetconfTransaction.RETRY_COUNT);\r
}\r
\r
public static InstanceIdentifier<Nat> buildNatIid(InstanceIdentifier<Interface> ifaceIid) {\r
return ifaceIid.builder().augmentation(NatInterfaceAugmentation.class).child(Nat.class).build();\r
}\r
\r
- public static List<ExternalIpAddressPool> resolveDynamicNat(@Nonnull PolicyContext policyCtx) {\r
+ public static Optional<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix,\r
+ ReadOnlyTransaction rTx) {\r
+ Optional<RendererNodes> readFromDs =\r
+ DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererNodesIid(), rTx);\r
+ rTx.close();\r
+ if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
+ return Optional.absent();\r
+ }\r
+ RendererNodes rendererNodes = readFromDs.get();\r
+ List<RendererNode>\r
+ vppNodes =\r
+ rendererNodes.getRendererNode()\r
+ .stream()\r
+ .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class) != null)\r
+ .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class).getPhysicalInterface() != null)\r
+ .collect(Collectors.toList());\r
+ for (RendererNode rn : vppNodes) {\r
+ java.util.Optional<PhysicalInterface>\r
+ optResolvedIface =\r
+ rn.getAugmentation(VppInterfaceAugmentation.class)\r
+ .getPhysicalInterface()\r
+ .stream()\r
+ .filter(phIface -> phIface.getAddress() != null)\r
+ .filter(phIface -> phIface.getAddress()\r
+ .stream()\r
+ .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))\r
+ .findFirst();\r
+ if (optResolvedIface.isPresent()) {\r
+ return Optional.of(VppIidFactory.getRendererNodeIid(rn)\r
+ .builder()\r
+ .augmentation(VppInterfaceAugmentation.class)\r
+ .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))\r
+ .build());\r
+ }\r
+ }\r
+ return Optional.absent();\r
+ }\r
+\r
+ public static List<ExternalIpAddressPool> resolveDynamicNat(@Nonnull PolicyContext policyCtx,\r
+ List<MappingEntryBuilder> natEntries) {\r
List<RendererForwardingByTenant> rendererForwardingByTenant =\r
policyCtx.getPolicy().getConfiguration().getRendererForwarding().getRendererForwardingByTenant();\r
Map<Long, Ipv4Prefix> hm = new HashMap<>();\r
for (AllocationPool pool : subnet.getSubnet().getAllocationPool()) {\r
if (subnet.getSubnet().getIpPrefix().getIpv4Prefix() != null) {\r
hm.putAll(resolveIpv4Prefix(subnet.getSubnet().getIpPrefix().getIpv4Prefix(),\r
- pool.getFirst(), pool.getLast()));\r
+ pool.getFirst(), pool.getLast(), natEntries));\r
}\r
}\r
}\r
}\r
List<ExternalIpAddressPool> extIps = new ArrayList<>();\r
for (Entry<Long, Ipv4Prefix> entry : hm.entrySet()) {\r
- new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey()).setExternalIpPool(entry.getValue()).build();\r
+ extIps.add(new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey())\r
+ .setExternalIpPool(entry.getValue())\r
+ .build());\r
}\r
return extIps;\r
}\r
\r
+ @VisibleForTesting\r
private static Map<Long,Ipv4Prefix> resolveIpv4Prefix(@Nonnull Ipv4Prefix prefix, @Nonnull String first,\r
- @Nullable String last) {\r
+ @Nullable String last, @Nullable List<MappingEntryBuilder> natEntries) {\r
+ LOG.trace("Resolving Ipv4Prefix. prefix: {}, first: {}, last: {}", prefix.getValue(), first, last);\r
SubnetUtils subnet = new SubnetUtils(prefix.getValue());\r
Map<Long,Ipv4Prefix> ext = new HashMap<>();\r
int min = subnet.getInfo().asInteger(first);\r
if (asInt < min) {\r
continue;\r
}\r
- ext.put(Long.valueOf(asInt), new Ipv4Prefix(addr + "/32"));\r
- if (last == null || subnet.getInfo().asInteger(addr) > subnet.getInfo().asInteger(last)) {\r
+ ext.put(Integer.toUnsignedLong(asInt), new Ipv4Prefix(addr + "/32"));\r
+ if (last == null || subnet.getInfo().asInteger(addr) >= subnet.getInfo().asInteger(last)) {\r
break;\r
}\r
}\r
+ if (natEntries != null) {\r
+ for (MappingEntryBuilder natEntry : natEntries) {\r
+ Ipv4Address externalSrcAddress = natEntry.getExternalSrcAddress();\r
+ long id = Integer.toUnsignedLong(subnet.getInfo().asInteger(externalSrcAddress.getValue()));\r
+ if (ext.get(id) != null) {\r
+ ext.remove(id);\r
+ }\r
+ }\r
+ }\r
return ext;\r
}\r
}\r
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListUtil;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatUtil;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListUtil;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
+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.common.rev140421.ContextId;
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.forwarding.l2_l3.rev160427.IpPrefixType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.NetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.NatAddressRenderer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints;
private final AclManager aclManager;
private final BridgeDomainManager bdManager;
private final NatManager natManager;
+ private final RoutingManager routingManager;
private final DataBroker dataBroker;
public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull AclManager aclManager,
- @Nonnull NatManager natManager, @Nonnull BridgeDomainManager bdManager, @Nonnull DataBroker dataBroker) {
+ @Nonnull NatManager natManager, @Nonnull RoutingManager routingManager, @Nonnull BridgeDomainManager bdManager,
+ @Nonnull DataBroker dataBroker) {
this.ifaceManager = Preconditions.checkNotNull(ifaceManager);
this.bdManager = Preconditions.checkNotNull(bdManager);
this.natManager = Preconditions.checkNotNull(natManager);
+ this.routingManager = Preconditions.checkNotNull(routingManager);
this.dataBroker = Preconditions.checkNotNull(dataBroker);
this.aclManager = Preconditions.checkNotNull(aclManager);
}
for (RendererNetworkDomain rendDomain : rendNetDomains) {
Optional<IpPrefix> resolvedIpPrefix = resolveIpPrefix(rendDomain);
if (resolvedIpPrefix.isPresent()) {
- Optional<InstanceIdentifier<PhysicalInterface>> resPhIface = natManager.resolvePhysicalInterface(resolvedIpPrefix.get());
+ Optional<InstanceIdentifier<PhysicalInterface>> resPhIface =
+ NatUtil.resolvePhysicalInterface(resolvedIpPrefix.get(), dataBroker.newReadOnlyTransaction());
if (resPhIface.isPresent()) {
physIfaces.add(resPhIface.get());
}
if (addrEp.getAugmentation(NatAddressRenderer.class) == null) {
continue;
}
+ String enpointIP = resolveEpIpAddressForSnat(addrEp);
+
+ if (enpointIP == null) {
+ LOG.warn("Endpoints {} IP cannot be null, skipping processing of SNAT", addrEp);
+ }
+
NatAddressRenderer natAddr = addrEp.getAugmentation(NatAddressRenderer.class);
if (natAddr.getNatAddress() == null && natAddr.getNatAddress().getIpv4Address() == null) {
- LOG.warn("Only Ipv4 SNAT is currently supported. Cannot apply SNAT for [{},{}]", addrEp.getAddress(),
+ LOG.warn("Only Ipv4 SNAT is currently supported. Cannot apply SNAT for [{},{}]", enpointIP,
natAddr.getNatAddress());
continue;
}
- Optional<MappingEntryBuilder> entry = natManager.resolveSnatEntry(addrEp.getAddress(), natAddr.getNatAddress()
+ Optional<MappingEntryBuilder> entry = natManager.resolveSnatEntry(enpointIP, natAddr.getNatAddress()
.getIpv4Address());
if (entry.isPresent()) {
sNatEntries.add(entry.get());
return sNatEntries;
}
+ private String resolveEpIpAddressForSnat(AddressEndpointWithLocation addrEp) {
+ if (addrEp.getAddressType().equals(MacAddressType.class)) {
+ ParentEndpointChoice parentEndpointChoice = addrEp.getParentEndpointChoice();
+ if (parentEndpointChoice instanceof ParentEndpointCase
+ && !((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().isEmpty()) {
+ ParentEndpoint parentEndpoint = ((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().get(0);
+ if (parentEndpoint.getAddressType().equals(IpPrefixType.class)) {
+ String[] ipWithPrefix = parentEndpoint.getAddress().split("/");
+ return ipWithPrefix[0];
+ } else {
+ LOG.warn("Endpoint {} Does not have a Parent Ep with IP for SNAT. skipping processing of SNAT",
+ addrEp);
+ return null;
+ }
+
+ } else {
+ LOG.warn("Endpoint {} Does not contain IP address for SNAT. skipping processing of SNAT", addrEp);
+ return null;
+ }
+ } else if (addrEp.getAddressType().equals(IpPrefixType.class)) {
+ return addrEp.getAddress();
+ }
+ return null;
+ }
+
@VisibleForTesting
void setTimer(byte time) {
WAIT_FOR_BD_PROCESSING = time;
}
+
+ public void syncRouting(PolicyContext policyCtx) {
+ Configuration cfg = policyCtx.getPolicy().getConfiguration();
+ if (cfg != null && cfg.getRendererForwarding() != null) {
+ for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) {
+ if (fwd == null) {
+ continue;
+ }
+
+ List<InstanceIdentifier<PhysicalInterface>>
+ physIfacesIid = resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain());
+ Map<InstanceIdentifier<?>, RoutingCommand> routingCommandMap =
+ routingManager.createRouting(fwd, physIfacesIid, General.Operations.PUT);
+
+ routingCommandMap.forEach((node, command) -> {
+ if (command != null && routingManager.submitRouting(command, node)) {
+ LOG.debug("Routing was successfully applied: {}.", command);
+ }
+ });
+ }
+ }
+ }
+
+ public void deleteRouting(PolicyContext policyCtx) {
+ Configuration cfg = policyCtx.getPolicy().getConfiguration();
+ if (cfg != null && cfg.getRendererForwarding() != null) {
+ for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) {
+ if (fwd == null) {
+ continue;
+ }
+
+ List<InstanceIdentifier<PhysicalInterface>>
+ physIfacesIid = resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain());
+ Map<InstanceIdentifier<?>, RoutingCommand> routingCommandMap =
+ routingManager.createRouting(fwd, physIfacesIid, General.Operations.DELETE);
+ routingCommandMap.forEach((node, command) -> {
+ if (command != null && routingManager.submitRouting(command, node)) {
+ LOG.debug("Routing was successfully removed: {}.", command);
+ }
+ });
+ }
+ }
+ }
}
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+
public class VppRendererPolicyManager {
private static final Logger LOG = LoggerFactory.getLogger(VppRendererPolicyManager.class);
}
private void rendererPolicyUpdated(RendererPolicy rPolicyBefore, RendererPolicy rPolicyAfter) {
+ LOG.trace("VPP renderer policy updated");
PolicyContext policyCtxBefore = new PolicyContext(rPolicyBefore);
PolicyContext policyCtxAfter = new PolicyContext(rPolicyAfter);
MapDifference<String, Collection<NodeId>> vppNodesByL2FlDiff =
fwManager.syncNatEntries(policyCtxAfter);
+ fwManager.deleteRouting(policyCtxBefore);
+ fwManager.syncRouting(policyCtxAfter);
+
SetView<RendererEndpointKey> createdRendEps = Sets.difference(rendEpsAfter, rendEpsBefore);
LOG.debug("Created renderer endpoints {}", createdRendEps);
createdRendEps.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtxAfter));
}
private void rendererPolicyCreated(RendererPolicy rPolicy) {
+ LOG.trace("VPP renderer policy version {} created", rPolicy.getVersion());
PolicyContext policyCtx = new PolicyContext(rPolicy);
ImmutableSet<RendererEndpointKey> rEpKeys = policyCtx.getPolicyTable().rowKeySet();
SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
fwManager.createBridgeDomainOnNodes(vppNodesByL2Fd);
fwManager.syncNatEntries(policyCtx);
+ fwManager.syncRouting(policyCtx);
rEpKeys.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtx));
}
private void rendererPolicyDeleted(RendererPolicy rendererPolicy) {
+ LOG.trace("VPP renderer policy version {} deleted", rendererPolicy.getVersion());
PolicyContext policyCtx = new PolicyContext(rendererPolicy);
ImmutableSet<RendererEndpointKey> rEpKeys = policyCtx.getPolicyTable().rowKeySet();
SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
fwManager.deleteNatEntries(policyCtx);
+ fwManager.deleteRouting(policyCtx);
fwManager.removeBridgeDomainOnNodes(vppNodesByL2Fd);
}
public void writeAcl(@Nonnull DataBroker mountPoint, @Nonnull InterfaceKey ifaceKey) {
Acl builtAcl = this.buildVppAcl(ifaceKey);
- LOG.info("Writing access-list {}", builtAcl.getAclName());
+ LOG.trace("Writing access-list {}", builtAcl.getAclName());
boolean write = GbpNetconfTransaction.netconfSyncedWrite(mountPoint,
VppIidFactory.getVppAcl(resolveAclName(ifaceKey)), builtAcl, GbpNetconfTransaction.RETRY_COUNT);
if (!write) {
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems. 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.renderer.vpp.routing;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+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.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.RendererForwardingByTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RoutingManager {
+ private static final Logger LOG = LoggerFactory.getLogger(RoutingManager.class);
+
+ private static final long DEFAULT_TABLE = 0L;
+
+ private final DataBroker dataBroker;
+ private final MountedDataBrokerProvider mountDataProvider;
+
+ public RoutingManager(DataBroker dataBroker, MountedDataBrokerProvider mountDataProvider) {
+ this.dataBroker = dataBroker;
+ this.mountDataProvider = mountDataProvider;
+ }
+
+ public Map<InstanceIdentifier<?>, RoutingCommand> createRouting(
+ @Nonnull RendererForwardingByTenant forwardingByTenant, List<InstanceIdentifier<PhysicalInterface>> physIntIids,
+ General.Operations operation) {
+
+ Map<InstanceIdentifier<?>, RoutingCommand> routingCommands = new HashMap<>();
+
+ getExternalGateways(forwardingByTenant.getRendererNetworkDomain()).forEach((gateways, virtualRouterIp) -> {
+ LOG.trace("Creating routing for Tenant {}, gateway {}, virtualRouterIp {}.",
+ forwardingByTenant.getTenantId(), gateways, virtualRouterIp);
+ List<Route> ipv4Routes = new ArrayList<>();
+ PhysicalInterface outboundInterface = resolveOutboundInterface(virtualRouterIp, physIntIids);
+ InstanceIdentifier<?> node = resolveOutboundNode(virtualRouterIp, physIntIids);
+
+ String outboundIntName = outboundInterface != null ? outboundInterface.getInterfaceName() : null;
+
+ if (Strings.isNullOrEmpty(outboundIntName)) {
+ LOG.trace("Route skipped, no physical interface for gateway found {} in interfaces {}", gateways,
+ physIntIids);
+ } else {
+ Long routeIndex = 0L;
+ IpAddress externalGwIp = gateways.getGateway();
+ for (Prefixes prefixes : gateways.getPrefixes()) {
+ routeIndex++;
+ Route ipv4Route = buildIpv4Route(outboundIntName, routeIndex, externalGwIp, prefixes);
+ //todo add support for ipv6
+ LOG.trace("Adding new route {}.", ipv4Route);
+ ipv4Routes.add(ipv4Route);
+ }
+ }
+
+ if (!ipv4Routes.isEmpty()) {
+ RoutingCommand command = routingCommands.put(node, new RoutingCommand.RoutingCommandBuilder()
+ .setOperation(operation)
+ .setRouterProtocol("learned-protocol-0")
+ .setRoutes(ipv4Routes)
+ //todo in multi-tenant environment we need to use different vrfID for each tenant
+ .setVrfId(DEFAULT_TABLE)
+ .build());
+ LOG.trace("Creating of routing successful, routing command: {}.", command);
+ }
+ });
+
+ return routingCommands;
+ }
+
+ private Route buildIpv4Route(String outboundIntName, Long routeIndex, IpAddress externalGwIp, Prefixes prefixes) {
+ return new RouteBuilder().setId(routeIndex)
+ .setDestinationPrefix(new Ipv4Prefix(prefixes.getPrefix().getIpv4Prefix()))
+ .setNextHopOptions(new SimpleNextHopBuilder().setNextHop(new Ipv4Address(externalGwIp.getIpv4Address()))
+ .setOutgoingInterface(outboundIntName)
+ .build())
+ .build();
+ }
+
+ /**
+ * Used to extract external gateways from network domains if they contain any gateways
+ * @param rendererNetworkDomain list of network domains from which we extract external gateways
+ * @return map of extracted gateways by virtual router IP from network domain list.
+ */
+ private Map<Gateways, IpAddress> getExternalGateways(List<RendererNetworkDomain> rendererNetworkDomain){
+ Map<Gateways, IpAddress> gateways = new HashMap<>();
+ for (RendererNetworkDomain domain : rendererNetworkDomain) {
+ SubnetAugmentRenderer subnet = domain.getAugmentation(SubnetAugmentRenderer.class);
+ IpAddress virtualRouterIp = subnet.getSubnet().getVirtualRouterIp();
+ if (virtualRouterIp == null){
+ continue;
+ }
+ List<Gateways> gatewaysList = subnet.getSubnet().getGateways();
+ if (gatewaysList != null) {
+ for (Gateways gateway : gatewaysList) {
+ gateways.put(gateway, virtualRouterIp);
+ LOG.trace("Found external Gateway {}", gateway);
+ }
+ }
+ }
+ return gateways;
+ }
+
+ private PhysicalInterface resolveOutboundInterface(@Nonnull IpAddress extIfaceIp,
+ List<InstanceIdentifier<PhysicalInterface>> physIntIids) {
+ LOG.trace("Resolving External interface {} from interfaces {}.", extIfaceIp, physIntIids);
+ for (InstanceIdentifier<PhysicalInterface> identifier : physIntIids) {
+ Optional<PhysicalInterface> physicalInterfaceOptional = DataStoreHelper.readFromDs(
+ LogicalDatastoreType.OPERATIONAL, identifier, dataBroker.newReadOnlyTransaction());
+ if (!physicalInterfaceOptional.isPresent()) {
+ continue;
+ }
+ if (physicalInterfaceOptional.get().isExternal()) {
+ return physicalInterfaceOptional.get();
+ }
+ if (physicalInterfaceOptional.get().getAddress().contains(extIfaceIp)){
+ return physicalInterfaceOptional.get();
+ }
+ }
+ return null;
+ }
+
+ private InstanceIdentifier<?> resolveOutboundNode(@Nonnull IpAddress extIfaceIp,
+ List<InstanceIdentifier<PhysicalInterface>> physIntIids) {
+ for (InstanceIdentifier<PhysicalInterface> identifier : physIntIids) {
+ Optional<PhysicalInterface> physicalInterfaceOptional = DataStoreHelper.readFromDs(
+ LogicalDatastoreType.OPERATIONAL, identifier, dataBroker.newReadOnlyTransaction());
+ if (!physicalInterfaceOptional.isPresent()){
+ continue;
+ }
+ if (physicalInterfaceOptional.get().isExternal()) {
+ return identifier.firstKeyOf(RendererNode.class).getNodePath();
+ }
+ if (physicalInterfaceOptional.get().getAddress().contains(extIfaceIp)){
+ return identifier.firstKeyOf(RendererNode.class).getNodePath();
+ }
+ }
+ return null;
+ }
+
+ public boolean submitRouting(@Nonnull RoutingCommand routing, InstanceIdentifier<?> nodeIid) {
+ if (nodeIid == null) {
+ LOG.info("NodeId is null Cannot create routing. RoutingCommand: {}", routing);
+ return false;
+ }
+ LOG.trace("Submitting routing for routing command: {}, nodeId: {}", routing, nodeIid);
+
+ Optional<DataBroker> mountPointDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid);
+ if (!mountPointDataBroker.isPresent()) {
+ throw new IllegalStateException("Cannot find data broker for mount point " + nodeIid);
+ }
+ LOG.info("Routing was created for forwarding. Routing: {}, for node: {}", routing, nodeIid);
+ if (routing.getOperation() == General.Operations.PUT){
+ return GbpNetconfTransaction.netconfSyncedWrite(mountPointDataBroker.get(), routing,
+ GbpNetconfTransaction.RETRY_COUNT);
+ } else if (routing.getOperation() == General.Operations.DELETE){
+ return GbpNetconfTransaction.netconfSyncedDelete(mountPointDataBroker.get(), routing,
+ GbpNetconfTransaction.RETRY_COUNT);
+ }
+ return false;
+ }
+}
return ruleBuilder;
}
- private SourcePortRangeBuilder resolveSourcePortRange(Map<String, ParameterValue> params, String portParam, String portRangeParam) {
- LOG.info("Updating dest port params:{}", params);
+ private SourcePortRangeBuilder resolveSourcePortRange(Map<String, ParameterValue> params, String portParam,
+ String portRangeParam) {
SourcePortRangeBuilder srcRange = new SourcePortRangeBuilder();
if (params.get(portParam) != null) {
PortNumber portNumber = new PortNumber(params.get(portParam).getIntValue().intValue());
return srcRange;
}
- private DestinationPortRangeBuilder resolveDestinationPortRange(Map<String, ParameterValue> params, String portParam, String portRangeParam) {
- LOG.info("Updating source port params:{}", params);
+ private DestinationPortRangeBuilder resolveDestinationPortRange(Map<String, ParameterValue> params,
+ String portParam, String portRangeParam) {
DestinationPortRangeBuilder dstRange = new DestinationPortRangeBuilder();
if (params.get(portParam) != null) {
PortNumber portNumber = new PortNumber(params.get(portParam).getIntValue().intValue());
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import com.google.common.util.concurrent.CheckedFuture;
public class GbpNetconfTransaction {
return result;
}
+ /***
+ * Netconf wrapper method for synced requests for write operation on a Netconf Device
+ * @param mountpoint netconf device
+ * @param command routing command that needs to be executed
+ * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
+ * @return true if transaction is successful, false otherwise
+ */
+ public static boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint, @Nonnull final RoutingCommand command,
+ byte retryCounter) {
+ VbdNetconfTransaction.REENTRANT_LOCK.lock();
+ boolean result = write(mountpoint, command, retryCounter);
+ VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+ return result;
+ }
+
/***
* Netconf wrapper method for synced requests for delete operation on a Netconf Device
* @param mountpoint netconf device
return result;
}
+ /***
+ * Netconf wrapper method for synced requests for delete operation on a Netconf Device
+ * @param mountpoint netconf device
+ * @param command routing command that needs to be executed
+ * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
+ * @return true if transaction is successful, false otherwise
+ */
+ public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
+ @Nonnull final RoutingCommand command, byte retryCounter) {
+ VbdNetconfTransaction.REENTRANT_LOCK.lock();
+ boolean result = deleteIfExists(mountpoint, command, retryCounter);
+ VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+ return result;
+ }
/**
* Use {@link ConfigCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
}
}
+ /**
+ * Use {@link RoutingCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
+ *
+ * @param mountpoint to access remote device
+ * @param command routing command with data, datastore type and iid
+ * @param retryCounter number of attempts
+ * @return true if transaction is successful, false otherwise
+ */
+ private static boolean write(final DataBroker mountpoint, final RoutingCommand command, byte retryCounter) {
+ LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
+ Preconditions.checkNotNull(mountpoint);
+ final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
+ try {
+ command.execute(rwTx);
+ final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
+ futureTask.get();
+ LOG.trace("Netconf WRITE transaction done for command {}", command);
+ return true;
+ } catch (Exception e) {
+ // Retry
+ if (retryCounter > 0) {
+ LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
+ return write(mountpoint, command, --retryCounter);
+ } else {
+ LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
+ return false;
+ }
+ }
+ }
+
/**
* Write data to remote device. Transaction is restarted if failed
*
* @param <T> generic data type. Has to be child of {@link DataObject}
* @return true if transaction is successful, false otherwise
*/
- private static <T extends DataObject> boolean write(final DataBroker mountpoint,
- final InstanceIdentifier<T> iid,
- final T data,
- byte retryCounter) {
+ private static <T extends DataObject> boolean write(final DataBroker mountpoint, final InstanceIdentifier<T> iid,
+ final T data, byte retryCounter) {
LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
Preconditions.checkNotNull(mountpoint);
final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
* @return optional data object if successful, {@link Optional#absent()} if failed
*/
public static synchronized <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
- final LogicalDatastoreType datastoreType,
- final InstanceIdentifier<T> iid,
- byte retryCounter) {
+ final LogicalDatastoreType datastoreType, final InstanceIdentifier<T> iid, byte retryCounter) {
LOG.trace("Netconf READ transaction started. RetryCounter: {}", retryCounter);
Preconditions.checkNotNull(mountpoint);
final ReadOnlyTransaction rTx = mountpoint.newReadOnlyTransaction();
Optional<T> data;
try {
final CheckedFuture<Optional<T>, ReadFailedException> futureData =
- rTx.read(datastoreType, iid);
+ rTx.read(datastoreType, iid);
data = futureData.get();
LOG.trace("Netconf READ transaction done. Data present: {}", data.isPresent());
return data;
* @param retryCounter number of attempts
* @return true if transaction is successful, false otherwise
*/
- private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command,
- byte retryCounter) {
+ private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command, byte retryCounter) {
Preconditions.checkNotNull(mountpoint);
InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(command.getInterfaceBuilder().getKey());
return deleteIfExists(mountpoint, iid, retryCounter);
}
+ /**
+ * Remove data from remote device using {@link ConfigCommand}
+ *
+ * @param mountpoint to access remote device
+ * @param command config command with data, datastore type and iid
+ * @param retryCounter number of attempts
+ * @return true if transaction is successful, false otherwise
+ */
+ private static boolean deleteIfExists(final DataBroker mountpoint, final RoutingCommand command,
+ byte retryCounter) {
+ Preconditions.checkNotNull(mountpoint);
+ String routerProtocol = command.getRouterProtocol();
+ if (Strings.isNullOrEmpty(routerProtocol)) {
+ routerProtocol = "learned-protocol-0";
+ }
+ InstanceIdentifier<RoutingProtocol> iid =
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol));
+ return deleteIfExists(mountpoint, iid, retryCounter);
+ }
+
/**
* Remove data from remote device. Data presence is verified before removal. Transaction is restarted if failed.
*
* @return true if transaction is successful, false otherwise
*/
private static <T extends DataObject> boolean deleteIfExists(final DataBroker mountpoint,
- final InstanceIdentifier<T> iid,
- byte retryCounter) {
+ final InstanceIdentifier<T> iid, byte retryCounter) {
LOG.trace("Netconf DELETE transaction started. Data will be read at first. RetryCounter: {}", retryCounter);
Preconditions.checkNotNull(mountpoint);
final Optional<T> optionalObject = read(mountpoint, LogicalDatastoreType.CONFIGURATION, iid, RETRY_COUNT);
if (!optionalObject.isPresent()) {
LOG.warn("Netconf DELETE transaction aborted. Data to remove are not present or cannot be read. Iid: {}",
- iid);
+ iid);
// Return true, this state is not considered as an error
return true;
}
package org.opendaylight.groupbasedpolicy.renderer.vpp.util;
import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstances;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Routing;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.RoutingProtocols;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
.child(NatInstance.class, new NatInstanceKey(natInstance))
.build();
}
+
+ public static InstanceIdentifier<RoutingProtocol> getRoutingInstanceIid(
+ final RoutingProtocolKey routingProtocolKey) {
+ return InstanceIdentifier.builder(Routing.class)
+ .child(RoutingInstance.class, new RoutingInstanceKey(RoutingCommand.ROUTER_INSTANCE_NAME))
+ .child(RoutingProtocols.class)
+ .child(RoutingProtocol.class, routingProtocolKey)
+ .build();
+ }
}
--- /dev/null
+# INITIAL VPP HOSTCONFIG CONFIGURATION
+#
+# Uncomment lines on the bottom of this file to change
+# default values of vpp-renderer bundle config.
+# The file should be placed to karaf_root_dir/etc
+#
+# To explicitly specify which physical interface of a
+# node should be used public interface, uncomment and modify the
+# line on the bottom of this document. Specifying one physical
+# interface per node is currently supported.
+#
+#public-interfaces = compute1:TenGigabitEthernet8/0/0,compute2:TenGigabitEthernet8/0/0
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
odl:use-default-for-reference-types="true">
<reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
<reference id="broker" interface="org.opendaylight.controller.sal.binding.api.BindingAwareBroker"/>
<reference id="clusterSingletonService" interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/>
+ <cm:property-placeholder persistent-id="org.opendaylight.groupbasedpolicy.vpp.startup" update-strategy="none">
+ <cm:default-properties>
+ <cm:property name="public-interfaces" value="unspecified"/>
+ </cm:default-properties>
+ </cm:property-placeholder>
+
<bean id="vppRenderer" class="org.opendaylight.controller.config.yang.config.vpp_provider.impl.GbpVppProviderInstance"
init-method="initialize" destroy-method="close">
<argument ref="dataBroker"/>
<argument ref="broker"/>
<argument ref="clusterSingletonService" />
+ <argument value="${public-interfaces}"/>
</bean>
<odl:rpc-implementation ref="vppRenderer"/>
-</blueprint>
\ No newline at end of file
+</blueprint>
leaf-list address {
type inet-types:ip-address;
}
+ leaf external {
+ type boolean;
+ default "false";
+ }
}
}
@Test
public void testCreateVppRenderer() throws Exception {
- VppRenderer vppRenderer = new VppRenderer(dataBroker, bindingAwareBroker);
+ VppRenderer vppRenderer = new VppRenderer(dataBroker, bindingAwareBroker, null);
vppRenderer.onSessionInitiated(providerContext);
import com.google.common.collect.ImmutableList;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Routing;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;\r
@Override\r
public Collection<Class<?>> getClassesFromModules() {\r
return ImmutableList.of(Interfaces.class, Interface.class, VhostUser.class, NetworkTopology.class,\r
- Topology.class, Node.class, NetconfNode.class, Renderer.class, LocationProviders.class, Config.class,\r
- NatInterfaceAugmentation.class);\r
+ Topology.class, Node.class, NetconfNode.class, Renderer.class, LocationProviders.class, Config.class,\r
+ NatInterfaceAugmentation.class, Routing.class, StaticRoutes1.class);\r
}\r
}\r
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems. 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.renderer.vpp.commands;
+
+import com.google.common.base.Optional;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.VppRendererDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.VppIpv4RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Static;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol.StaticRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttr;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttrBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.routing.instance.routing.protocols.routing.protocol.VppProtocolAttributesBuilder;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+public class RoutingCommandTest extends VppRendererDataBrokerTest {
+
+ private final static String NEXT_HOP = "10.0.0.1";
+ private final static String OUT_INTERFACE = "GigabitEthernet0/a/0";
+ private final static String PREFIX = "10.0.0.0/24";
+ private final static String PREFIX_2 = "0.0.0.0/0";
+ private final static String ROUTER_PROTOCOL = "vpp-routing-protocol_0";
+ private final static String ROUTE1_DESCRIPTION = "route 1";
+ private final static String ROUTE2_DESCRIPTION = "route 2";
+ private final static VniReference VNI_REFERENCE = new VniReference(0L);
+ private final static Route
+ ROUTE_1 =
+ new RouteBuilder().setId(1L)
+ .setDescription(ROUTE1_DESCRIPTION)
+ .setDestinationPrefix(new Ipv4Prefix(PREFIX))
+ .setNextHopOptions(new SimpleNextHopBuilder().setNextHop(new Ipv4Address(NEXT_HOP))
+ .setOutgoingInterface(OUT_INTERFACE)
+ .build())
+ .setVppIpv4Route(new VppIpv4RouteBuilder().setClassifyTable("0").setSecondaryVrf(VNI_REFERENCE).build())
+ .build();
+ private final static Route
+ ROUTE_2 =
+ new RouteBuilder().setId(2L)
+ .setDescription(ROUTE2_DESCRIPTION)
+ .setDestinationPrefix(new Ipv4Prefix(PREFIX_2))
+ .setNextHopOptions(new SimpleNextHopBuilder().setNextHop(new Ipv4Address(NEXT_HOP))
+ .setOutgoingInterface(OUT_INTERFACE)
+ .build())
+ .setVppIpv4Route(new VppIpv4RouteBuilder().setClassifyTable("0").setSecondaryVrf(VNI_REFERENCE).build())
+ .build();
+ private final static List<Route> ROUTES = Collections.singletonList(ROUTE_1);
+ private final static List<Route> ROUTES2 = Collections.singletonList(ROUTE_2);
+
+ private final static RoutingProtocol ROUTING_PROTOCOL = new RoutingProtocolBuilder()
+ .setEnabled(true)
+ .setType(Static.class)
+ .setName(ROUTER_PROTOCOL)
+ .addAugmentation(RoutingProtocolVppAttr.class, new RoutingProtocolVppAttrBuilder().setVppProtocolAttributes(
+ new VppProtocolAttributesBuilder().setPrimaryVrf(VNI_REFERENCE).build()).build())
+ .setStaticRoutes(new StaticRoutesBuilder().addAugmentation(StaticRoutes1.class,
+ new StaticRoutes1Builder().setIpv4(new Ipv4Builder().setRoute(ROUTES).build()).build()).build())
+ .build();
+
+ private DataBroker dataBroker;
+
+ @Before
+ public void init() {
+ dataBroker = getDataBroker();
+ }
+
+ @Test
+ public void addRoutingCommandTest() throws ExecutionException, InterruptedException {
+ ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
+
+ RoutingCommand
+ routingCommand =
+ RoutingCommand.builder()
+ .setOperation(General.Operations.PUT)
+ .setRouterProtocol(ROUTER_PROTOCOL)
+ .setRoutes(ROUTES)
+ .setVrfId(VNI_REFERENCE.getValue())
+ .build();
+
+ Assert.assertEquals(General.Operations.PUT, routingCommand.getOperation());
+ Assert.assertEquals(ROUTER_PROTOCOL, routingCommand.getRouterProtocol());
+ Assert.assertEquals(VNI_REFERENCE.getValue(), routingCommand.getVrfId());
+ Assert.assertEquals(ROUTES, routingCommand.getRoutes());
+
+ Optional<RoutingProtocol> routingProtocolOptional = executeCommand(rwTx, routingCommand);
+
+ Assert.assertTrue(routingProtocolOptional.isPresent());
+ Assert.assertEquals(ROUTING_PROTOCOL, routingProtocolOptional.get());
+ }
+
+ @Test
+ public void removeRoutingCommandTest() throws ExecutionException, InterruptedException {
+ Optional<RoutingProtocol> optional = writeBasicRoutingProtocol();
+ ReadWriteTransaction rwTx;
+
+ Assert.assertTrue(optional.isPresent());
+
+ rwTx = dataBroker.newReadWriteTransaction();
+ RoutingCommand routingCommand =
+ RoutingCommand.builder()
+ .setOperation(General.Operations.DELETE)
+ .setRouterProtocol(ROUTER_PROTOCOL)
+ .setVrfId(VNI_REFERENCE.getValue())
+ .build();
+ routingCommand.execute(rwTx);
+ rwTx.submit();
+
+ optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routingCommand.getRouterProtocol())),
+ dataBroker.newReadOnlyTransaction());
+
+ Assert.assertFalse(optional.isPresent());
+ }
+
+ @Test
+ public void mergeRoutingCommandTest() throws ExecutionException, InterruptedException {
+ Optional<RoutingProtocol> optional = writeBasicRoutingProtocol();
+ ReadWriteTransaction rwTx;
+
+ Assert.assertTrue(optional.isPresent());
+
+ rwTx = dataBroker.newReadWriteTransaction();
+
+ RoutingCommand
+ routingCommand =
+ RoutingCommand.builder()
+ .setOperation(General.Operations.MERGE)
+ .setRouterProtocol(ROUTER_PROTOCOL)
+ .setRoutes(ROUTES2)
+ .setVrfId(VNI_REFERENCE.getValue())
+ .build();
+
+ routingCommand.execute(rwTx);
+ rwTx.submit();
+
+ optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routingCommand.getRouterProtocol())),
+ dataBroker.newReadOnlyTransaction());
+
+ Assert.assertTrue(optional.isPresent());
+ RoutingProtocol routingProtocol = optional.get();
+ StaticRoutes1 staticRoutes1 = routingProtocol.getStaticRoutes().getAugmentation(StaticRoutes1.class);
+ Assert.assertTrue(staticRoutes1.getIpv4().getRoute().contains(ROUTE_1));
+ Assert.assertTrue(staticRoutes1.getIpv4().getRoute().contains(ROUTE_2));
+ }
+
+ private Optional<RoutingProtocol> writeBasicRoutingProtocol() throws InterruptedException, ExecutionException {
+ ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(ROUTER_PROTOCOL)), ROUTING_PROTOCOL, true);
+ rwTx.submit().get();
+
+ return DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(ROUTER_PROTOCOL)),
+ dataBroker.newReadOnlyTransaction());
+ }
+
+ private Optional<RoutingProtocol> executeCommand(ReadWriteTransaction rwTx, RoutingCommand routingCommand)
+ throws ExecutionException, InterruptedException {
+ routingCommand.execute(rwTx);
+
+ rwTx.submit().get();
+
+ ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+
+ return DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routingCommand.getRouterProtocol())), rTx);
+ }
+}
.thenReturn(Optional.of(mountPoint));
Mockito.when(mountPoint.getService(Matchers.<Class<DataBroker>>any())).thenReturn(Optional.of(dataBroker2));
dataBroker = getDataBroker();
- vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+ vppNodeManager = new VppNodeManager(dataBroker, providerContext, null);
vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager, new EventBus());
}
package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
-import javax.annotation.Nonnull;
-
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
+import javax.annotation.Nonnull;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
private final static NodeId VPP_NODE_ID = new NodeId("vppNode");
private final static Topology BASE_TOPOLOGY = new TopologyBuilder().setTopologyId(BASE_TOPOLOGY_ID)
.setNode(Collections.singletonList(new NodeBuilder().setNodeId(VPP_NODE_ID)
- .setSupportingNode(Collections.singletonList(new SupportingNodeBuilder().setTopologyRef(SUPPORTING_TOPOLOGY_NETCONF)
+ .setSupportingNode(Collections.singletonList(new SupportingNodeBuilder()
+ .setTopologyRef(SUPPORTING_TOPOLOGY_NETCONF)
.setNodeRef(VPP_NODE_ID)
.build()))
.build()))
final InterfaceManager interfaceManager = Mockito.mock(InterfaceManager.class);
final AclManager aclManager = Mockito.mock(AclManager.class);
final NatManager natManager = Mockito.mock(NatManager.class);
+ final RoutingManager routingManager = Mockito.mock(RoutingManager.class);
final ForwardingManager fwManager =
- new ForwardingManager(interfaceManager, aclManager, natManager, bridgeDomainManager, dataBroker);
+ new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bridgeDomainManager,
+ dataBroker);
fwManager.setTimer((byte) 1);
}
import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
private BridgeDomainManager bdManager;
@Mock
private NatManager natManager;
+ @Mock
+ private RoutingManager routingManager;
private ForwardingManager fwdManager;
@Before
public void init() {
- fwdManager = new ForwardingManager(ifaceManager, aclManager,natManager, bdManager, getDataBroker());
+ fwdManager =
+ new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, getDataBroker());
}
@Override
Mockito.when(bdManager.createVlanBridgeDomainOnVppNode(Mockito.eq(BD_1), Mockito.any(VlanId.class),
Mockito.eq(NODE_1)))
.thenReturn(Futures.immediateFuture(null));
- GbpBridgeDomain bd = new GbpBridgeDomainBuilder().setId(BD_1).setType(VlanNetwork.class).setVlan(VLAN_1).build();
+ GbpBridgeDomain bd =
+ new GbpBridgeDomainBuilder().setId(BD_1).setType(VlanNetwork.class).setVlan(VLAN_1).build();
InstanceIdentifier<GbpBridgeDomain> bdIid =
InstanceIdentifier.builder(Config.class).child(GbpBridgeDomain.class, bd.getKey()).build();
WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
String clientIp = "1.1.1.1";
String clientIfaceName = "client1";
String bdNameOnVpp = "bdRed";
- AbsoluteLocation clientLocation = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, clientIfaceName);
+ AbsoluteLocation clientLocation =
+ DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, clientIfaceName);
AddressEndpointWithLocation clientEp =
DtoFactory.createEndpoint(clientIp, DtoFactory.L2FD_CTX.getValue(), clientLocation);
String webIp = "2.2.2.2";
String webIfaceName = "web1";
- AbsoluteLocation webLocation = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, webIfaceName);
+ AbsoluteLocation webLocation =
+ DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, webIfaceName);
AddressEndpointWithLocation webEp =
DtoFactory.createEndpoint(webIp, DtoFactory.L2FD_CTX.getValue(), webLocation);
Configuration configuration = DtoFactory.createConfiguration(Arrays.asList(clientEp), Arrays.asList(webEp));
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationProvider;
import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2;
private AclManager aclManager;
private ForwardingManager fwManager;
private NatManager natManager;
+ private RoutingManager routingManager;
private VppRendererPolicyManager vppRendererPolicyManager;
@Override
ifaceManager = new InterfaceManager(mountedDataProviderMock, dataBroker);
aclManager = new AclManager(mountedDataProviderMock);
natManager = new NatManager(dataBroker, mountedDataProviderMock);
+ routingManager = new RoutingManager(dataBroker, mountedDataProviderMock);
bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
- fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, bdManager, dataBroker);
+ fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, dataBroker);
vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
fwManager.setTimer((byte) 1);
}