From 89b6216d5a960e18174056ab10a381dda11b7b33 Mon Sep 17 00:00:00 2001 From: Shakib Ahmed Date: Thu, 11 May 2017 23:05:57 -0700 Subject: [PATCH] Add implementation for flat L3 overlay For flat L3 overlay, we need to put extra configs on top of regular LISP configs. We need to enable proxy arp for interfaces, put proxy arp ranges, put static routing, static arp. On top, we have to create loopback interface, set unnumbered interfaces and add GPE action for a route. This patch implements: - Enable proxy arp for every port interface - Add proxy arp per subnet for a host - Add static routing for every port interface - Add static arp for every port interface - Add loopback interface per subnet for a host for unnumbered Change-Id: I3779efe03855ac6602f397caaf5492c3c42d27f6 Signed-off-by: Shakib Ahmed --- .../config/vpp_provider/impl/VppRenderer.java | 13 +- .../commands/AbstractInterfaceCommand.java | 23 +- .../vpp/commands/LoopbackCommand.java | 18 +- .../vpp/commands/LoopbackCommandWrapper.java | 65 +++++ .../vpp/commands/ProxyRangeCommand.java | 136 ++++++++++ .../vpp/commands/StaticArpCommand.java | 132 +++++++++ .../renderer/vpp/commands/TapPortCommand.java | 25 ++ .../vpp/commands/VhostUserCommand.java | 26 ++ .../renderer/vpp/iface/InterfaceManager.java | 19 +- .../renderer/vpp/iface/VppPathMapper.java | 18 ++ .../renderer/vpp/lisp/LispState.java | 7 + .../renderer/vpp/lisp/LispStateManager.java | 2 +- .../vpp/lisp/bvi/BviHostSpecificInfo.java | 84 ------ .../renderer/vpp/lisp/bvi/BviManager.java | 151 ----------- .../event/manager/GbpSubnetEventManager.java | 70 +++++ .../lisp/flat/overlay/FlatOverlayManager.java | 192 +++++++++++++ .../vpp/lisp/flat/overlay/RoutingInfo.java | 32 +++ .../flat/overlay/StaticRoutingHelper.java | 156 +++++++++++ .../vpp/lisp/loopback/LoopbackManager.java | 254 ++++++++++++++++++ .../vpp/lisp/loopback/SubnetHostInfo.java | 55 ++++ .../HostVrfRoutingInformationMapper.java | 74 +++++ .../InterfaceNameToRouteInfoMapper.java | 56 ++++ .../LoopbackHostSpecificInfoMapper.java | 135 ++++++++++ .../lisp/mappers/StaticRouteInfoMapper.java | 44 +++ .../mappers/SubnetUuidToGbpSubnetMapper.java | 43 +++ .../vpp/lisp/util/ConfigManagerHelper.java | 23 ++ .../renderer/vpp/lisp/util/IpAddressUtil.java | 29 ++ .../vpp/policy/ForwardingManager.java | 27 +- .../vpp/util/GbpNetconfTransaction.java | 50 ++++ .../renderer/vpp/util/VppIidFactory.java | 30 +++ .../policy/BridgeDomainManagerImplTest.java | 8 +- .../vpp/policy/ForwardingManagerTest.java | 9 +- .../policy/VppRendererPolicyManagerTest.java | 11 +- 33 files changed, 1746 insertions(+), 271 deletions(-) create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommandWrapper.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ProxyRangeCommand.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/StaticArpCommand.java delete mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviHostSpecificInfo.java delete mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviManager.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/event/manager/GbpSubnetEventManager.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/RoutingInfo.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/StaticRoutingHelper.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/LoopbackManager.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/SubnetHostInfo.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/HostVrfRoutingInformationMapper.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/InterfaceNameToRouteInfoMapper.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/LoopbackHostSpecificInfoMapper.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/StaticRouteInfoMapper.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/SubnetUuidToGbpSubnetMapper.java create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/IpAddressUtil.java diff --git a/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java b/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java index 6b50c3e5a..80c8a9801 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java +++ b/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java @@ -24,7 +24,9 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.event.manager.GbpSubnetEventManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.GbpSubnetListener; import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyListener; import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppEndpointListener; @@ -80,6 +82,7 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider { private VppEndpointListener vppEndpointListener; private RendererPolicyListener rendererPolicyListener; private GbpSubnetListener vppGbpSubnetListener; + private GbpSubnetEventManager subnetEventManager; VppRenderer(@Nonnull DataBroker dataBroker, @Nonnull BindingAwareBroker bindingAwareBroker, @Nullable String publicInterfaces) { @@ -143,14 +146,16 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider { AclManager aclManager = new AclManager(mountDataProvider); NatManager natManager = new NatManager(dataBroker, mountDataProvider); LispStateManager lispStateManager = new LispStateManager(mountDataProvider); - BviManager bviManager = new BviManager(mountDataProvider); + FlatOverlayManager flatOverlayManager = new FlatOverlayManager(mountDataProvider); + LoopbackManager loopbackManager = new LoopbackManager(mountDataProvider); + subnetEventManager = new GbpSubnetEventManager(loopbackManager); dtoEventBus.register(interfaceManager); - dtoEventBus.register(bviManager); + dtoEventBus.register(subnetEventManager); RoutingManager routingManager = new RoutingManager(dataBroker, mountDataProvider); bdManager = new BridgeDomainManagerImpl(dataBroker); ForwardingManager fwManager = new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bdManager, - lispStateManager, bviManager,dataBroker); + lispStateManager, loopbackManager, flatOverlayManager, dataBroker); VppRendererPolicyManager vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker); dtoEventBus.register(vppRendererPolicyManager); diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java index 27d7bdeee..8b921d646 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java @@ -16,6 +16,9 @@ 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.interfaces.rev140508.interfaces.InterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyArpInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyArpInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.interfaces._interface.ProxyArpBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,8 +30,10 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa protected General.Operations operation; protected String name; protected String description; - String bridgeDomain; - Boolean enabled; + protected String bridgeDomain; + protected Boolean enabled; + protected Boolean enableProxyArp; + protected Long vrfId; public General.Operations getOperation() { return operation; @@ -38,6 +43,10 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa return name; } + public Long getVrfId() { + return vrfId; + } + public String getDescription() { return description; } @@ -47,7 +56,7 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa return this; } - String getBridgeDomain() { + public String getBridgeDomain() { return bridgeDomain; } @@ -98,4 +107,12 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa return VppIidFactory.getInterfaceIID(this.getInterfaceBuilder().getKey()); } + protected void addEnableProxyArpAugmentation(InterfaceBuilder interfaceBuilder) { + if (enableProxyArp != null) { + ProxyArpInterfaceAugmentationBuilder augmentationBuilder = new ProxyArpInterfaceAugmentationBuilder(); + augmentationBuilder.setProxyArp((new ProxyArpBuilder()).build()); + interfaceBuilder.addAugmentation(ProxyArpInterfaceAugmentation.class, augmentationBuilder.build()); + } + } + } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommand.java index b9f5a679b..97e4690bf 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommand.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommand.java @@ -44,7 +44,6 @@ public class LoopbackCommand extends AbstractInterfaceCommand { private boolean bvi; private IpAddress ipAddress; private IpPrefix ipPrefix; - private Long vrfId; private LoopbackCommand(LoopbackCommandBuilder builder) { this.name = builder.getInterfaceName(); @@ -57,6 +56,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand { this.ipAddress = builder.getIpAddress(); this.ipPrefix = builder.getIpPrefix(); this.vrfId = builder.getVrfId(); + this.enableProxyArp = builder.getEnableProxyArp(); } public static LoopbackCommandBuilder builder() { @@ -79,10 +79,6 @@ public class LoopbackCommand extends AbstractInterfaceCommand { return ipPrefix; } - Long getVrfId() { - return vrfId; - } - @Override public InterfaceBuilder getInterfaceBuilder() { InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setKey(new InterfaceKey(name)) @@ -115,6 +111,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand { .build())).build()); interfaceBuilder.addAugmentation(Interface1.class, interface1Builder.build()); interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build()); + addEnableProxyArpAugmentation(interfaceBuilder); return interfaceBuilder; } @@ -127,7 +124,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand { public String toString() { return "LoopPortUserCommand [physAddress=" + physAddress + ", IpAddress=" + ipAddress + ", IpPrefix=" + ipPrefix + ", bridgeDomain=" + bridgeDomain + ", operations=" + operation + ", name=" + name + ", description=" - + description + ", enabled=" + enabled + ", bvi=" + bvi + "]"; + + description + ", enabled=" + enabled + ", bvi=" + bvi + ", enableProxyArp=" + enableProxyArp + "]"; } private short getPrefixLength() { @@ -146,6 +143,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand { private IpAddress ipAddress; private IpPrefix ipPrefix; private Long vrfId; + private Boolean enableProxyArp; public String getInterfaceName() { return interfaceName; @@ -237,6 +235,14 @@ public class LoopbackCommand extends AbstractInterfaceCommand { return this; } + public Boolean getEnableProxyArp() { + return enableProxyArp; + } + + public void setEnableProxyArp(Boolean enableProxyArp) { + this.enableProxyArp = enableProxyArp; + } + /** * LoopPortCommand build method. * diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommandWrapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommandWrapper.java new file mode 100644 index 000000000..5a023a77d --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommandWrapper.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017 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 org.opendaylight.groupbasedpolicy.renderer.vpp.util.General; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; + +/** + * Created by Shakib Ahmed on 5/16/17. + */ +public class LoopbackCommandWrapper { + + public static LoopbackCommand simpleLoopbackPutCommand(String interfaceName, + long vrf, + IpAddress ipAddress, + IpPrefix cidr) { + LoopbackCommand.LoopbackCommandBuilder simpleLoopbackCommandBuilder = + simpleLoopbackCommandBuilder(interfaceName, vrf, ipAddress, cidr); + simpleLoopbackCommandBuilder.setOperation(General.Operations.PUT); + return simpleLoopbackCommandBuilder.build(); + } + + public static LoopbackCommand bviLoopbackPutCommand(String interfaceName, + long vrf, + IpAddress ipAddress, + IpPrefix cidr, + String bridgeDomainName) { + LoopbackCommand.LoopbackCommandBuilder bviLoopbackCommandBuilder = + bviLoopbackCommandBuilder(interfaceName, vrf, ipAddress, cidr, bridgeDomainName); + bviLoopbackCommandBuilder.setOperation(General.Operations.PUT); + return bviLoopbackCommandBuilder.build(); + } + + private static LoopbackCommand.LoopbackCommandBuilder simpleLoopbackCommandBuilder(String interfaceName, + long vrf, + IpAddress ipAddress, + IpPrefix cidr) { + LoopbackCommand.LoopbackCommandBuilder loopbackCommandBuilder = new LoopbackCommand.LoopbackCommandBuilder(); + loopbackCommandBuilder.setInterfaceName(interfaceName); + loopbackCommandBuilder.setEnabled(true); + loopbackCommandBuilder.setVrfId(vrf); + loopbackCommandBuilder.setIpAddress(ipAddress); + loopbackCommandBuilder.setIpPrefix(cidr); + return loopbackCommandBuilder; + } + + private static LoopbackCommand.LoopbackCommandBuilder bviLoopbackCommandBuilder(String interfaceName, + long vrf, + IpAddress ipAddress, + IpPrefix cidr, + String bridgeDomainName) { + LoopbackCommand.LoopbackCommandBuilder simpleLoopbackCommandBuilder = + simpleLoopbackCommandBuilder(interfaceName, vrf, ipAddress, cidr); + simpleLoopbackCommandBuilder.setBridgeDomain(bridgeDomainName); + simpleLoopbackCommandBuilder.setBvi(true); + return simpleLoopbackCommandBuilder; + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ProxyRangeCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ProxyRangeCommand.java new file mode 100644 index 000000000..1a65afebe --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ProxyRangeCommand.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017 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.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRange; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRangeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRangeKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by Shakib Ahmed on 5/3/17. + */ +public class ProxyRangeCommand extends AbstractConfigCommand { + private static final Logger LOG = LoggerFactory.getLogger(ProxyRangeCommand.class); + + private Long vrf; + private Ipv4Address startAddress; + private Ipv4Address endAddress; + + public ProxyRangeCommand(ProxyRangeCommandBuilder builder) { + this.operation = builder.getOperation(); + this.vrf = builder.getVrf(); + this.startAddress = builder.getStartAddress(); + this.endAddress = builder.getEndAddress(); + } + + public static ProxyRangeCommandBuilder builder() { + return new ProxyRangeCommandBuilder(); + } + + @Override + public InstanceIdentifier getIid() { + return VppIidFactory.getProxyRangeIid(vrf, startAddress, endAddress); + } + + @Override + void put(ReadWriteTransaction rwTx) { + InstanceIdentifier proxyRangeInstanceIid = VppIidFactory.getProxyRangeIid(vrf, startAddress, endAddress); + rwTx.put(LogicalDatastoreType.CONFIGURATION, proxyRangeInstanceIid, getProxyRangeBuilder().build(), true); + } + + @Override + void merge(ReadWriteTransaction rwTx) { + InstanceIdentifier proxyRangeInstanceIdentifier = VppIidFactory. + getProxyRangeIid(vrf, startAddress, endAddress); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, proxyRangeInstanceIdentifier, getProxyRangeBuilder().build(), true); + } + + @Override + void delete(ReadWriteTransaction rwTx) { + try { + InstanceIdentifier proxyRangeInstanceIdentifier = VppIidFactory. + getProxyRangeIid(vrf, startAddress, endAddress); + rwTx.delete(LogicalDatastoreType.CONFIGURATION, proxyRangeInstanceIdentifier); + } catch (IllegalStateException ex) { + LOG.debug("Proxy Range not deleted from DS {}", this, ex); + } + } + + private ProxyRangeBuilder getProxyRangeBuilder() { + return new ProxyRangeBuilder() + .setKey(new ProxyRangeKey(this.endAddress, this.startAddress, this.vrf)) + .setVrfId(this.vrf) + .setLowAddr(this.startAddress) + .setHighAddr(this.endAddress); + } + + + public static class ProxyRangeCommandBuilder { + + private General.Operations operation; + private Long vrf; + private Ipv4Address startAddress; + private Ipv4Address endAddress; + + public Long getVrf() { + return vrf; + } + + public void setVrf(Long vrf) { + this.vrf = vrf; + } + + public Ipv4Address getStartAddress() { + return startAddress; + } + + public void setStartAddress(Ipv4Address startAddress) { + this.startAddress = startAddress; + } + + public Ipv4Address getEndAddress() { + return endAddress; + } + + public void setEndAddress(Ipv4Address endAddress) { + this.endAddress = endAddress; + } + + public General.Operations getOperation() { + return operation; + } + + public void setOperation(General.Operations operation) { + this.operation = operation; + } + + /** + * ProxyRangeCommand build method. + * + * @return ProxyRangeCommand + * @throws IllegalArgumentException if vrf, operation, startAddress or endAddress is null. + */ + public ProxyRangeCommand build() { + Preconditions.checkNotNull(operation, "Operation must not be null!"); + Preconditions.checkNotNull(vrf, "vrf must not be null!"); + Preconditions.checkNotNull(startAddress, "StartAddress must not be null!"); + Preconditions.checkNotNull(endAddress, "EndAddress must not be null!"); + return new ProxyRangeCommand(this); + } + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/StaticArpCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/StaticArpCommand.java new file mode 100644 index 000000000..64204f063 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/StaticArpCommand.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017 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.inet.types.rev130715.Ipv4AddressNoZone; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by Shakib Ahmed on 5/3/17. + */ +public class StaticArpCommand extends AbstractConfigCommand{ + private static final Logger LOG = LoggerFactory.getLogger(StaticArpCommand.class); + + private Ipv4AddressNoZone ip; + private PhysAddress linkLayerAddress; + private InterfaceKey interfaceKey; + + public StaticArpCommand(NeighborCommandBuilder builder) { + this.operation = builder.getOperation(); + this.ip = builder.getIp(); + this.linkLayerAddress = builder.getLinkLayerAddress(); + this.interfaceKey = builder.getInterfaceKey(); + } + + public static NeighborCommandBuilder builder() { + return new NeighborCommandBuilder(); + } + + @Override + public InstanceIdentifier getIid() { + return VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip)); + } + + @Override + void put(ReadWriteTransaction rwTx) { + InstanceIdentifier iid = VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip)); + rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, getNeighborBuilder().build()); + } + + @Override + void merge(ReadWriteTransaction rwTx) { + InstanceIdentifier iid = VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip)); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, iid, getNeighborBuilder().build()); + } + + @Override + void delete(ReadWriteTransaction rwTx) { + try { + InstanceIdentifier iid = VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip)); + rwTx.delete(LogicalDatastoreType.CONFIGURATION, iid); + } catch (IllegalStateException ex) { + LOG.debug("Proxy Range not deleted from DS {}", this, ex); + } + } + + private NeighborBuilder getNeighborBuilder() { + return new NeighborBuilder() + .setKey(new NeighborKey(this.ip)) + .setIp(this.ip) + .setLinkLayerAddress(this.linkLayerAddress); + } + + public static class NeighborCommandBuilder { + private General.Operations operation; + private Ipv4AddressNoZone ip; + private PhysAddress linkLayerAddress; + private InterfaceKey interfaceKey; + + public General.Operations getOperation() { + return operation; + } + + public void setOperation(General.Operations operation) { + this.operation = operation; + } + + public Ipv4AddressNoZone getIp() { + return ip; + } + + public void setIp(Ipv4AddressNoZone ip) { + this.ip = ip; + } + + public PhysAddress getLinkLayerAddress() { + return linkLayerAddress; + } + + public void setLinkLayerAddress(PhysAddress linkLayerAddress) { + this.linkLayerAddress = linkLayerAddress; + } + + public InterfaceKey getInterfaceKey() { + return interfaceKey; + } + + public void setInterfaceKey(InterfaceKey interfaceKey) { + this.interfaceKey = interfaceKey; + } + + /** + * StaticArpCommand build method. + * + * @return StaticArpCommand + * @throws IllegalArgumentException if ip or operation is null. + */ + public StaticArpCommand build() { + Preconditions.checkNotNull(operation, "Operation must not be null!"); + Preconditions.checkNotNull(ip, "ip must not be null!"); + + return new StaticArpCommand(this); + } + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/TapPortCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/TapPortCommand.java index 7f277799a..5a3612815 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/TapPortCommand.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/TapPortCommand.java @@ -20,6 +20,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.RoutingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.TapBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.l2.base.attributes.interconnection.BridgeBasedBuilder; @@ -38,6 +39,7 @@ public class TapPortCommand extends AbstractInterfaceCommand { this.description = builder.getDescription(); this.bridgeDomain = builder.getBridgeDomain(); this.deviceInstance = builder.getDeviceInstance(); + this.enableProxyArp = builder.getEnableProxyArp(); } public static TapPortCommandBuilder builder() { @@ -73,12 +75,17 @@ public class TapPortCommand extends AbstractInterfaceCommand { .setDeviceInstance(this.deviceInstance) .build()); + if (getVrfId() != null) { + vppAugmentationBuilder.setRouting(new RoutingBuilder().setIpv4VrfId(getVrfId()).build()); + } + if (!Strings.isNullOrEmpty(bridgeDomain)) { vppAugmentationBuilder.setL2(new L2Builder() .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomain).build()).build()); } interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build()); + addEnableProxyArpAugmentation(interfaceBuilder); return interfaceBuilder; } @@ -99,6 +106,8 @@ public class TapPortCommand extends AbstractInterfaceCommand { private String description; private Long deviceInstance = null; private boolean enabled = true; + private Boolean enableProxyArp; + private Long vrfId; String getInterfaceName() { return interfaceName; @@ -172,6 +181,22 @@ public class TapPortCommand extends AbstractInterfaceCommand { return this; } + public Boolean getEnableProxyArp() { + return enableProxyArp; + } + + public void setEnableProxyArp(Boolean enableProxyArp) { + this.enableProxyArp = enableProxyArp; + } + + public Long getVrfId() { + return vrfId; + } + + public void setVrfId(Long vrfId) { + this.vrfId = vrfId; + } + /** * TapPortCommand build method. * diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java index d9ad9d89d..2a60ddf33 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java @@ -19,6 +19,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.RoutingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.VhostUserBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.l2.base.attributes.interconnection.BridgeBasedBuilder; @@ -35,6 +36,7 @@ public class VhostUserCommand extends AbstractInterfaceCommand { this.enabled = builder.isEnabled(); this.description = builder.getDescription(); this.bridgeDomain = builder.getBridgeDomain(); + this.enableProxyArp = builder.getEnableProxyArp(); } @@ -64,12 +66,18 @@ public class VhostUserCommand extends AbstractInterfaceCommand { // Create the vhost augmentation VppInterfaceAugmentationBuilder vppAugmentationBuilder = new VppInterfaceAugmentationBuilder() .setVhostUser(new VhostUserBuilder().setRole(role).setSocket(socket).build()); + + if (getVrfId() != null) { + vppAugmentationBuilder.setRouting(new RoutingBuilder().setIpv4VrfId(getVrfId()).build()); + } + if (!Strings.isNullOrEmpty(bridgeDomain)) { vppAugmentationBuilder.setL2(new L2Builder() .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomain).build()).build()); } interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build()); + addEnableProxyArpAugmentation(interfaceBuilder); return interfaceBuilder; } @@ -89,6 +97,8 @@ public class VhostUserCommand extends AbstractInterfaceCommand { private boolean enabled = true; private String description; private String bridgeDomain; + private Boolean enableProxyArp; + private Long vrfId; public String getName() { return name; @@ -153,6 +163,22 @@ public class VhostUserCommand extends AbstractInterfaceCommand { return this; } + public Boolean getEnableProxyArp() { + return enableProxyArp; + } + + public void setEnableProxyArp(Boolean enableProxyArp) { + this.enableProxyArp = enableProxyArp; + } + + public Long getVrfId() { + return vrfId; + } + + public void setVrfId(Long vrfId) { + this.vrfId = vrfId; + } + /** * VhostUserCommand build method. * diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java index d8da56669..22f7851ad 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java @@ -174,7 +174,7 @@ public class InterfaceManager implements AutoCloseable { LOG.trace("Creating VPP endpoint {}, type of {}", vppEndpoint, interfaceTypeChoice); Optional potentialIfaceCommand = Optional.absent(); if (interfaceTypeChoice instanceof VhostUserCase) { - potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT); + potentialIfaceCommand = createVhostInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT); } else if (interfaceTypeChoice instanceof TapCase) { potentialIfaceCommand = createTapInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT); } else if (interfaceTypeChoice instanceof LoopbackCase){ @@ -249,7 +249,7 @@ public class InterfaceManager implements AutoCloseable { LOG.trace("Deleting VPP endpoint {}, type of {}", vppEndpoint, interfaceTypeChoice.toString()); Optional potentialIfaceCommand = Optional.absent(); if (interfaceTypeChoice instanceof VhostUserCase) { - potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE); + potentialIfaceCommand = createVhostInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE); } else if (interfaceTypeChoice instanceof TapCase) { potentialIfaceCommand = createTapInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE); } else if (interfaceTypeChoice instanceof LoopbackCase){ @@ -315,8 +315,8 @@ public class InterfaceManager implements AutoCloseable { } } - private Optional createInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp, - @Nonnull Operations operations) { + private Optional createVhostInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp, + @Nonnull Operations operations) { if (!hasNodeAndInterface(vppEp)) { LOG.debug("Interface command is not created for {}", vppEp); return Optional.absent(); @@ -334,6 +334,11 @@ public class InterfaceManager implements AutoCloseable { builder.setSocket(socket); builder.setRole(VhostUserRole.Client); } + + if (ConfigUtil.getInstance().isL3FlatEnabled()) { + builder.setEnableProxyArp(true); + } + VhostUserCommand vhostUserCommand = builder.setOperation(operations).setDescription(vppEp.getDescription()).build(); return Optional.of(vhostUserCommand); @@ -355,8 +360,12 @@ public class InterfaceManager implements AutoCloseable { return Optional.absent(); } builder.setTapName(name); - builder.setPhysAddress(tapIface.getPhysicalAddress()); } + + if (ConfigUtil.getInstance().isL3FlatEnabled()) { + builder.setEnableProxyArp(true); + } + TapPortCommand tapPortCommand = builder .setOperation(operation) .setDescription(vppEp.getDescription()) diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java index 6cebc3f85..a802c1bdc 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java @@ -53,6 +53,24 @@ public class VppPathMapper { return Optional.of(VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceName))); } + public static Optional interfacePathToInterfaceName(@Nullable String restPath) { + if (Strings.isNullOrEmpty(restPath)) { + return Optional.absent(); + } + if (restPath.length() < INTERFACE_PATH_MIN_LENGTH) { + return Optional.absent(); + } + if (!restPath.startsWith(INTERFACE_PATH_BEFORE_KEY)) { + return Optional.absent(); + } + if (!restPath.endsWith(INTERFACE_PATH_AFTER_KEY)) { + return Optional.absent(); + } + int endIndexInterfaceName = restPath.length() - INTERFACE_PATH_AFTER_KEY.length(); + String interfaceName = restPath.substring(INTERFACE_PATH_BEFORE_KEY.length(), endIndexInterfaceName); + return Optional.of(interfaceName); + } + public static String bridgeDomainToRestPath(String bridgeDomainName) { return BD_PATH_BEFORE_KEY + bridgeDomainName + BD_PATH_AFTER_KEY; } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispState.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispState.java index 9b46a7565..418fc56e8 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispState.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispState.java @@ -28,6 +28,7 @@ public class LispState { private Set vniSet; private boolean mapRegisteredEnabled; private HashMap eidToMappingIdMapper; + private int interfaceCount; public LispState(String hostName) { this.hostName = hostName; @@ -38,6 +39,7 @@ public class LispState { mapRegisteredEnabled = false; vniSet = new HashSet<>(); eidToMappingIdMapper = new HashMap<>(); + interfaceCount = 1; } public String getHostName() { @@ -105,6 +107,7 @@ public class LispState { } public void addInEidSet(Eid eid, String mappingId) { + interfaceCount++; eidToMappingIdMapper.put(eid, mappingId); } @@ -119,4 +122,8 @@ public class LispState { public String getEidMapping(Eid eid) { return eidToMappingIdMapper.get(eid); } + + public int getInterfaceId() { + return interfaceCount; + } } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispStateManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispStateManager.java index 95e11c309..c8684b4d8 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispStateManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispStateManager.java @@ -218,7 +218,7 @@ public class LispStateManager { private void addEidInEidTable(DataBroker vppDataBroker, LispState lispState, Eid eid) throws LispConfigCommandFailedException { - String mappingId = lispStateHelper.constructMappingName(lispState.eidCount()); + String mappingId = lispStateHelper.constructMappingName(lispState.getInterfaceId()); AbstractLispCommand addLocalMappingInEidTableCommand = LispCommandWrapper .addLocalMappingInEidTable(mappingId, eid, diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviHostSpecificInfo.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviHostSpecificInfo.java deleted file mode 100644 index b8315a261..000000000 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviHostSpecificInfo.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2017 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.lisp.bvi; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; - -import java.util.HashMap; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Created by Shakib Ahmed on 4/26/17. - */ -public class BviHostSpecificInfo { - private HashMap> hostIdToSubnetMapper; - private Multimap subnetUuidToHostIdList; - - public BviHostSpecificInfo() { - hostIdToSubnetMapper = new HashMap<>(); - subnetUuidToHostIdList = ArrayListMultimap.create(); - } - - private HashMap getSubnetsOfHost(String hostName) { - return hostIdToSubnetMapper.get(hostName); - } - - private void putSubnetInfoOfAHost(String hostId, String subnetUuid, String interfaceName) { - HashMap subnetsOfAHost = getSubnetsOfHost(hostId); - - if (subnetsOfAHost == null) { - subnetsOfAHost = new HashMap<>(); - hostIdToSubnetMapper.put(hostId, subnetsOfAHost); - } - subnetsOfAHost.put(subnetUuid, interfaceName); - } - - public boolean bviAlreadyExists(String hostName, String subnetUuid) { - return hostIdToSubnetMapper.containsKey(hostName) && - hostIdToSubnetMapper.get(hostName).containsKey(subnetUuid); - } - - public void addBviForHost(String hostName, String subnetUuid, String interfaceName) { - putSubnetInfoOfAHost(hostName, subnetUuid, interfaceName); - subnetUuidToHostIdList.put(subnetUuid, hostName); - } - - public int getBviCount(String hostName) { - if (hostIdToSubnetMapper.get(hostName) == null) { - return 0; - } - return hostIdToSubnetMapper.get(hostName).size(); - } - - public void clearSubnet(String subnetUuid) { - subnetUuidToHostIdList.get(subnetUuid).forEach(hostId -> { - deleteParticularSubnetFromHost(hostId, subnetUuid); - }); - subnetUuidToHostIdList.get(subnetUuid).clear(); - } - - private void deleteParticularSubnetFromHost(String hostId, String subnetUuid) { - hostIdToSubnetMapper.get(hostId).remove(subnetUuid); - } - - public List getHostsWithSubnet(String subnetUuid) { - return subnetUuidToHostIdList.get(subnetUuid).stream().collect(Collectors.toList()); - } - - public String getInterfaceNameForBviInHost(String hostId, String subnetUuid) { - if (hostIdToSubnetMapper.get(hostId) != null) { - return hostIdToSubnetMapper.get(hostId).get(subnetUuid); - } else { - return null; - } - } -} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviManager.java deleted file mode 100644 index 078a3fd8e..000000000 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviManager.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2017 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.lisp.bvi; - -import com.google.common.base.Preconditions; -import com.google.common.eventbus.Subscribe; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand; -import org.opendaylight.groupbasedpolicy.renderer.vpp.event.GbpSubnetEvent; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper; -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.renderer.vpp.util.VppIidFactory; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.ExecutionException; - -/** - * Created by Shakib Ahmed on 4/26/17. - */ -public class BviManager { - private static final Logger LOG = LoggerFactory.getLogger(BviManager.class); - - private ConfigManagerHelper managerHelper; - - private HashMap subnetInformation; - - private BviHostSpecificInfo bviHostSpecificInfo; - private NeutronTenantToVniMapper neutronTenantToVniMapper; - - public BviManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) { - managerHelper = new ConfigManagerHelper(mountedDataBrokerProvider); - subnetInformation = new HashMap<>(); - bviHostSpecificInfo = new BviHostSpecificInfo(); - neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance(); - } - - @Subscribe - public synchronized void gbpSubnetChanged(GbpSubnetEvent event) { - final GbpSubnet oldGbpSubnet = event.getBefore().orNull(); - final GbpSubnet newGbpSubnet = event.getAfter().orNull(); - switch (event.getDtoModificationType()) { - case CREATED: - Preconditions.checkNotNull(newGbpSubnet); - processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet); - break; - case UPDATED: - Preconditions.checkNotNull(oldGbpSubnet); - Preconditions.checkNotNull(newGbpSubnet); - processSubnetDeleted(oldGbpSubnet.getId()); - processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet); - break; - case DELETED: - Preconditions.checkNotNull(oldGbpSubnet); - processSubnetDeleted(oldGbpSubnet.getId()); - break; - } - } - - private void processSubnetCreated(String subnetUuid, GbpSubnet subnetInfo) { - subnetInformation.put(subnetUuid, subnetInfo); - } - - private void processSubnetDeleted(String subnetUuid) { - subnetInformation.remove(subnetUuid); - - deleteBviIfExists(subnetUuid); - } - - public GbpSubnet getSubnetInfo(String subnetUuid) { - return subnetInformation.get(subnetUuid); - } - - public void createBviIfNecessary(AddressEndpointWithLocation addressEp, - String bridgeDomainName) { - try { - DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(addressEp).get(); - String hostName = managerHelper.getHostName(addressEp).get(); - String subnetUuid = managerHelper.getSubnet(addressEp); - - if (bviHostSpecificInfo.bviAlreadyExists(hostName, subnetUuid)) { - return; - } - - GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid), - "Subnet UUID {} hasn't been created yet!", subnetUuid); - - LoopbackCommand.LoopbackCommandBuilder loopbackCommandBuilder = - new LoopbackCommand.LoopbackCommandBuilder(); - loopbackCommandBuilder.setInterfaceName("loop" - + bviHostSpecificInfo.getBviCount(hostName)); - loopbackCommandBuilder.setBridgeDomain(bridgeDomainName); - loopbackCommandBuilder.setBvi(true); - loopbackCommandBuilder.setEnabled(true); - loopbackCommandBuilder.setVrfId(getVni(addressEp.getTenant().getValue())); - loopbackCommandBuilder.setIpAddress(gbpSubnetInfo.getGatewayIp()); - loopbackCommandBuilder.setIpPrefix(gbpSubnetInfo.getCidr()); - loopbackCommandBuilder.setOperation(General.Operations.PUT); - createBviInterface(hostName, vppDataBroker, loopbackCommandBuilder); - } catch (LispConfigCommandFailedException e) { - LOG.debug("LISP loopback command failed for {}", e.getMessage()); - } - } - - public void createBviInterface(String hostName, DataBroker vppDataBroker, - LoopbackCommand.LoopbackCommandBuilder commandBuilder) throws LispConfigCommandFailedException { - - if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, - commandBuilder.build(), - GbpNetconfTransaction.RETRY_COUNT)) { - bviHostSpecificInfo.addBviForHost(hostName, - commandBuilder.getBridgeDomain(), - commandBuilder.getInterfaceName()); - } else { - throw new LispConfigCommandFailedException("BVI could not be created for " - + hostName + " and bridge domain " + commandBuilder.getBridgeDomain()); - } - } - - public void deleteBviIfExists(String subnetUuid) { - - List hostsWithSubnet = bviHostSpecificInfo.getHostsWithSubnet(subnetUuid); - - hostsWithSubnet.forEach(host -> { - DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(host).get(); - String bviInterfaceName = bviHostSpecificInfo.getInterfaceNameForBviInHost(host, subnetUuid); - GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker, - VppIidFactory.getInterfaceIID(new InterfaceKey(bviInterfaceName)), GbpNetconfTransaction.RETRY_COUNT); - }); - } - - private long getVni(String tenantUuid) { - return neutronTenantToVniMapper.getVni(tenantUuid); - } -} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/event/manager/GbpSubnetEventManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/event/manager/GbpSubnetEventManager.java new file mode 100644 index 000000000..a4c438ec5 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/event/manager/GbpSubnetEventManager.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 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.lisp.event.manager; + +import com.google.common.base.Preconditions; +import com.google.common.eventbus.Subscribe; +import org.opendaylight.groupbasedpolicy.renderer.vpp.event.GbpSubnetEvent; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.SubnetUuidToGbpSubnetMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; + +/** + * Created by Shakib Ahmed on 5/3/17. + */ +public class GbpSubnetEventManager { + private static final Logger LOG = LoggerFactory.getLogger(GbpSubnetEventManager.class); + + private SubnetUuidToGbpSubnetMapper subnetUuidToGbpSubnetInfoMapper; + private LoopbackManager loopbackManager; + + public GbpSubnetEventManager(@Nonnull LoopbackManager loopbackManager) { + this.loopbackManager = loopbackManager; + this.subnetUuidToGbpSubnetInfoMapper = SubnetUuidToGbpSubnetMapper.getInstance(); + } + + @Subscribe + public synchronized void gbpSubnetChanged(GbpSubnetEvent event) { + final GbpSubnet oldGbpSubnet = event.getBefore().orNull(); + final GbpSubnet newGbpSubnet = event.getAfter().orNull(); + + LOG.debug("GbpSubnet information updated.\nPrevious: {}\nPresent: {}\n", oldGbpSubnet, newGbpSubnet); + + switch (event.getDtoModificationType()) { + case CREATED: + Preconditions.checkNotNull(newGbpSubnet); + processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet); + break; + case UPDATED: + Preconditions.checkNotNull(oldGbpSubnet); + Preconditions.checkNotNull(newGbpSubnet); + processSubnetDeleted(oldGbpSubnet.getId()); + processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet); + break; + case DELETED: + Preconditions.checkNotNull(oldGbpSubnet); + processSubnetDeleted(oldGbpSubnet.getId()); + break; + } + } + + private void processSubnetCreated(String subnetUuid, GbpSubnet subnetInfo) { + subnetUuidToGbpSubnetInfoMapper.addSubnetInfo(subnetUuid, subnetInfo); + } + + private void processSubnetDeleted(String subnetUuid) { + subnetUuidToGbpSubnetInfoMapper.removeSubnetInfo(subnetUuid); + loopbackManager.deleteLoopbackIfExists(subnetUuid); + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java new file mode 100644 index 000000000..a671a1e0a --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2017 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.lisp.flat.overlay; + + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.StaticArpCommand; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.HostVrfRoutingInformationMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper; +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.renderer.vpp.util.VppIidFactory; +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.Ipv4AddressNoZone; +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.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.Routing; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.RoutingBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; + +/** + * Created by Shakib Ahmed on 5/2/17. + */ +public class FlatOverlayManager { + private static final Logger LOG = LoggerFactory.getLogger(FlatOverlayManager.class); + + private ConfigManagerHelper overlayHelper; + + private NeutronTenantToVniMapper neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance(); + private HostVrfRoutingInformationMapper hostVrfInfo = HostVrfRoutingInformationMapper.getInstance(); + + private StaticRoutingHelper staticRoutingHelper; + + public FlatOverlayManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) { + this.overlayHelper = new ConfigManagerHelper(mountedDataBrokerProvider); + staticRoutingHelper = new StaticRoutingHelper(); + } + + public void configureEndpointForFlatOverlay(AddressEndpointWithLocation addressEp) { + configureInterfaceForFlatOverlay(addressEp); + addStaticArp(addressEp); + addStaticRoute(addressEp); + } + + public void handleEndpointDeleteForFlatOverlay(AddressEndpointWithLocation addressEp) { + deleteStaticRoute(addressEp); + } + + private void configureInterfaceForFlatOverlay(AddressEndpointWithLocation addressEp) { + addInterfaceInVrf(addressEp); + } + + private void addInterfaceInVrf(AddressEndpointWithLocation addressEp) { + DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get(); + long vni = getVni(addressEp.getTenant().getValue()); + long vrf = vni; + Optional interfaceNameOptional = overlayHelper.getInterfaceName(addressEp); + + Preconditions.checkArgument(interfaceNameOptional.isPresent()); + + if (!putVrfInInterface(vppDataBroker, interfaceNameOptional.get(), vrf)) { + LOG.warn("Failed to put interface {} to vrf {}", interfaceNameOptional.get(), vrf); + } else { + LOG.debug("Added interface {} to vrf {}", interfaceNameOptional.get(), vrf); + } + } + + private boolean putVrfInInterface(DataBroker vppDataBroker, + String interfaceName, + Long vrf) { + InstanceIdentifier iid = VppIidFactory.getRoutingIid(new InterfaceKey(interfaceName)); + RoutingBuilder builder = new RoutingBuilder(); + builder.setIpv4VrfId(vrf); + return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT); + } + + private void addStaticArp(AddressEndpointWithLocation addressEp) { + DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get(); + String hostName = overlayHelper.getHostName(addressEp).get(); + String physicalAddress = overlayHelper.getPhysicalAddress(addressEp); + Optional interfaceNameOptional = overlayHelper.getInterfaceName(addressEp); + + Preconditions.checkArgument(interfaceNameOptional.isPresent()); + + String interfaceName = interfaceNameOptional.get(); + InterfaceKey interfaceKey = new InterfaceKey(interfaceName); + + Ipv4AddressNoZone ip = new Ipv4AddressNoZone(overlayHelper.getInterfaceIp(addressEp)); + + if (!putIpv4Neighbor(vppDataBroker, interfaceKey, new PhysAddress(physicalAddress), ip)) { + LOG.warn("Failed to put static arp with interface {} for ip={} and physical-address={}", interfaceName, + ip, physicalAddress); + } else { + LOG.debug("Added Static arp ({} {}) in host {} for interface {}", ip, physicalAddress, hostName, + interfaceName); + } + } + + private boolean putIpv4Neighbor(DataBroker vppDataBroker, + InterfaceKey interfaceKey, + PhysAddress physAddress, + Ipv4AddressNoZone ip) { + StaticArpCommand.NeighborCommandBuilder neighborCommandBuilder = new StaticArpCommand.NeighborCommandBuilder(); + + neighborCommandBuilder.setOperation(General.Operations.PUT); + neighborCommandBuilder.setInterfaceKey(interfaceKey); + neighborCommandBuilder.setIp(ip); + neighborCommandBuilder.setLinkLayerAddress(physAddress); + + return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, + neighborCommandBuilder.build(), GbpNetconfTransaction.RETRY_COUNT); + } + + private void addStaticRoute(AddressEndpointWithLocation addressEp) { + DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get(); + String hostName = overlayHelper.getHostName(addressEp).get(); + + long vni = getVni(addressEp.getTenant().getValue()); + long vrf = vni; + + if (!hostVrfInfo.vrfExists(hostName, vrf)) { + if (!staticRoutingHelper.addRoutingProtocolForVrf(vppDataBroker, hostName, vrf)) { + LOG.warn("Failed to add Routing protocol for host {} and vrf {}!", hostName, vrf); + } + } + + String outgoingInterfaceName = overlayHelper.getInterfaceName(addressEp).get(); + Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp); + + if (staticRoutingHelper.endPointRoutingExists(outgoingInterfaceName, ipWithoutPrefix)) { + return; + } + + Ipv4Prefix ipv4Prefix = overlayHelper.getInterfaceIpAsPrefix(addressEp); + + if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(vppDataBroker, + hostName, + vrf, + ipWithoutPrefix, + ipv4Prefix, + outgoingInterfaceName)) { + LOG.warn("Failed to add routing ({} via {}) in vrf {} in compute host {}!", + ipv4Prefix, outgoingInterfaceName, vrf, hostName); + } else { + LOG.debug("Added route ({} via {}) in vrf {} in compute host {}", + ipv4Prefix, outgoingInterfaceName, vrf, hostName); + } + } + + private void deleteStaticRoute(AddressEndpointWithLocation addressEp) { + DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get(); + String hostName = overlayHelper.getHostName(addressEp).get(); + String interfaceName = overlayHelper.getInterfaceName(addressEp).get(); + + long vni = getVni(addressEp.getTenant().getValue()); + long vrf = vni; + + Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp); + + if (!staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(vppDataBroker, + hostName, + vrf, + interfaceName)) { + LOG.warn("Failed to delete route ({} via {}) from vrf {} from host{}", + ipWithoutPrefix, interfaceName, vrf, hostName); + + } else { + LOG.debug("Delete Static Route ({} via {}) from vrf {} from host {}", + ipWithoutPrefix, interfaceName, vrf, hostName); + } + } + + private long getVni(String tenantUuid) { + return neutronTenantToVniMapper.getVni(tenantUuid); + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/RoutingInfo.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/RoutingInfo.java new file mode 100644 index 000000000..18853a928 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/RoutingInfo.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 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.lisp.flat.overlay; + +/** + * Created by Shakib Ahmed on 5/4/17. + */ +public class RoutingInfo { + private String ProtocolName; + private int count = 0; + + public String getProtocolName() { + return ProtocolName; + } + + public void setProtocolName(String protocolName) { + ProtocolName = protocolName; + } + + public int getCount() { + return count; + } + + public void incrementCount() { + count++; + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/StaticRoutingHelper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/StaticRoutingHelper.java new file mode 100644 index 000000000..b438a9140 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/StaticRoutingHelper.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017 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.lisp.flat.overlay; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.HostVrfRoutingInformationMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.InterfaceNameToRouteInfoMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; +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.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4; +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.RouteKey; +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.StaticRoutes; +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.Arrays; +import java.util.List; + +/** + * Created by Shakib Ahmed on 5/4/17. + */ +public class StaticRoutingHelper { + private static final Logger LOG = LoggerFactory.getLogger(StaticRoutingHelper.class); + + private static final String ROUTING_PROTOCOL_NAME_PREFIX = "static-routing-"; + private static final String DEFAULT_DESCRIPTION = "Static route added from GBP for flat L3 overlay"; + + private HostVrfRoutingInformationMapper hostVrfInfo = HostVrfRoutingInformationMapper.getInstance(); + + private InterfaceNameToRouteInfoMapper interfaceNameToRouteInfoMapper; + + public StaticRoutingHelper() { + interfaceNameToRouteInfoMapper = new InterfaceNameToRouteInfoMapper(); + } + + public synchronized boolean addRoutingProtocolForVrf(DataBroker vppDataBroker, + String hostId, + long vrf) { + String routingProtocolName = getRoutingProtocolName(vrf); + RoutingProtocolBuilder builder = new RoutingProtocolBuilder(); + builder.setKey(new RoutingProtocolKey(routingProtocolName)); + builder.setName(routingProtocolName); + builder.setType(Static.class); + builder.setDescription(DEFAULT_DESCRIPTION); + RoutingProtocolVppAttrBuilder vppAugmentationBuilder = new RoutingProtocolVppAttrBuilder(); + + vppAugmentationBuilder. + setVppProtocolAttributes(new VppProtocolAttributesBuilder() + .setPrimaryVrf(new VniReference(vrf)).build()); + + builder.addAugmentation(RoutingProtocolVppAttr.class, vppAugmentationBuilder.build()); + + InstanceIdentifier iid = VppIidFactory + .getRoutingInstanceIid(builder.getKey()); + if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, + iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT)) { + RoutingInfo info = new RoutingInfo(); + info.setProtocolName(routingProtocolName); + hostVrfInfo.addRoutingVrfToHost(hostId, vrf, info); + return true; + } + + return false; + } + + public boolean endPointRoutingExists(String interfaceName, Ipv4Address ip) { + return interfaceNameToRouteInfoMapper.routeAlreadyExists(interfaceName, ip); + } + + public synchronized boolean addSingleStaticRouteInRoutingProtocol(DataBroker vppDataBroker, + String hostId, + long vrf, + Ipv4Address nextHopAddress, + Ipv4Prefix ipPrefix, + String outgoingInterface) { + RouteBuilder builder = new RouteBuilder(); + + Long routingId = hostVrfInfo.getEndPointCountInVrf(hostId, vrf); + + builder.setId(routingId); + builder.setDestinationPrefix(ipPrefix); + builder.setKey(new RouteKey(builder.getId())); + builder.setNextHopOptions(new SimpleNextHopBuilder() + .setNextHop(nextHopAddress) + .setOutgoingInterface(outgoingInterface) + .build()); + + List routes = Arrays.asList(builder.build()); + + Ipv4 ipv4Route = new Ipv4Builder().setRoute(routes).build(); + + InstanceIdentifier iid = VppIidFactory. + getRoutingInstanceIid(new RoutingProtocolKey(hostVrfInfo.getProtocolName(hostId, vrf))) + .child(StaticRoutes.class) + .augmentation(StaticRoutes1.class) + .child(Ipv4.class); + + if (GbpNetconfTransaction.netconfSyncedMerge(vppDataBroker, iid, ipv4Route, GbpNetconfTransaction.RETRY_COUNT)) { + interfaceNameToRouteInfoMapper.addRouteForInterface(outgoingInterface, nextHopAddress, routingId); + hostVrfInfo.addStaticRoute(hostId, vrf); + return true; + } + + return false; + } + + public synchronized boolean deleteSingleStaticRouteFromRoutingProtocol(DataBroker vppDataBroker, + String hostId, + long vrf, + String outgoingInterface) { + List allRoutingIdsForPort = interfaceNameToRouteInfoMapper.getRoutingIdsAssociatedWithInterface(outgoingInterface); + + boolean allOk = true; + + for (Long routingId : allRoutingIdsForPort) { + InstanceIdentifier iid = VppIidFactory. + getRoutingInstanceIid(new RoutingProtocolKey(hostVrfInfo.getProtocolName(hostId, vrf))) + .child(StaticRoutes.class) + .augmentation(StaticRoutes1.class) + .child(Ipv4.class) + .child(Route.class, new RouteKey(routingId)); + if (!GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker, iid, GbpNetconfTransaction.RETRY_COUNT)) { + LOG.warn("Route delete failed for interface {} from {}", outgoingInterface, hostId); + allOk = false; + } + } + + interfaceNameToRouteInfoMapper.clearStaticRoutesForInterface(outgoingInterface); + return allOk; + } + + public static String getRoutingProtocolName(long vrf) { + return ROUTING_PROTOCOL_NAME_PREFIX + vrf; + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/LoopbackManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/LoopbackManager.java new file mode 100644 index 000000000..fd26f16b3 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/LoopbackManager.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2017 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.lisp.loopback; + +import com.google.common.base.Preconditions; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommandWrapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ProxyRangeCommand; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.LoopbackHostSpecificInfoMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.SubnetUuidToGbpSubnetMapper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.IpAddressUtil; +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.renderer.vpp.util.VppIidFactory; +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.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import java.util.List; + +/** + * Created by Shakib Ahmed on 4/26/17. + */ +public class LoopbackManager { + private static final Logger LOG = LoggerFactory.getLogger(LoopbackManager.class); + + private ConfigManagerHelper loopbackManagerHelper; + + private LoopbackHostSpecificInfoMapper subnetHostSpecificInfo; + private NeutronTenantToVniMapper neutronTenantToVniMapper; + private SubnetUuidToGbpSubnetMapper subnetUuidToGbpSubnetMapper; + + private static final String LOOP_NAME_PREFIX = "loop-"; + + public LoopbackManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) { + this.loopbackManagerHelper = new ConfigManagerHelper(mountedDataBrokerProvider); + this.subnetHostSpecificInfo = new LoopbackHostSpecificInfoMapper(); + this.neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance(); + this.subnetUuidToGbpSubnetMapper = SubnetUuidToGbpSubnetMapper.getInstance(); + } + + public void createBviLoopbackIfNeeded(AddressEndpointWithLocation addressEp, + String bridgeDomainName) { + try { + DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(addressEp).get(); + String hostName = loopbackManagerHelper.getHostName(addressEp).get(); + String subnetUuid = loopbackManagerHelper.getSubnet(addressEp); + + if (subnetHostSpecificInfo.loopbackAlreadyExists(hostName, subnetUuid)) { + subnetHostSpecificInfo.addNewPortInHostSubnet(hostName, subnetUuid); + return; + } + + GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid), + "Subnet UUID {} hasn't been created yet!", subnetUuid); + + String interfaceName = LOOP_NAME_PREFIX + subnetHostSpecificInfo.getLoopbackCount(hostName); + long vni = getVni(addressEp.getTenant().getValue()); + + LoopbackCommand bviLoopbackCommand = LoopbackCommandWrapper + .bviLoopbackPutCommand(interfaceName, vni, gbpSubnetInfo.getGatewayIp(), gbpSubnetInfo.getCidr(), + bridgeDomainName); + createLoopbackInterface(hostName, subnetUuid, vppDataBroker, bviLoopbackCommand); + } catch (LispConfigCommandFailedException e) { + LOG.warn("LISP couldn't be configured: {}", e.getMessage()); + } + } + + public void createSimpleLoopbackIfNeeded(AddressEndpointWithLocation addressEp) { + try { + DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(addressEp).get(); + String hostName = loopbackManagerHelper.getHostName(addressEp).get(); + String subnetUuid = loopbackManagerHelper.getSubnet(addressEp); + + if (subnetHostSpecificInfo.loopbackAlreadyExists(hostName, subnetUuid)) { + return; + } + + String interfaceName = LOOP_NAME_PREFIX + subnetHostSpecificInfo.getLoopbackCount(hostName); + long vni = getVni(addressEp.getTenant().getValue()); + long vrf = vni; + + GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid), + "Subnet UUID {} hasn't been created yet!", subnetUuid); + + LoopbackCommand simpleLoopbackCommand = LoopbackCommandWrapper + .simpleLoopbackPutCommand(interfaceName, vrf, gbpSubnetInfo.getGatewayIp(), + gbpSubnetInfo.getCidr()); + + createLoopbackInterface(hostName, subnetUuid, vppDataBroker, simpleLoopbackCommand); + addProxyArpRange(vppDataBroker, vrf, gbpSubnetInfo, hostName); + } catch (LispConfigCommandFailedException e) { + LOG.warn("LISP couldn't be configured: {}", e.getMessage()); + } + } + + private void createLoopbackInterface(String hostName, String subnetUuid, DataBroker vppDataBroker, + LoopbackCommand loopbackCommand) throws LispConfigCommandFailedException { + + if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, + loopbackCommand, + GbpNetconfTransaction.RETRY_COUNT)) { + subnetHostSpecificInfo.addLoopbackForHost(hostName, subnetUuid, loopbackCommand.getName(), + loopbackCommand.getVrfId()); + subnetHostSpecificInfo.addNewPortInHostSubnet(hostName, subnetUuid); + } else { + throw new LispConfigCommandFailedException("BVI could not be created for " + + hostName + " and bridge domain " + loopbackCommand.getBridgeDomain()); + } + } + + public void deleteLoopbackIfExists(String subnetUuid) { + + List hostsWithSubnet = subnetHostSpecificInfo.getHostsWithSubnet(subnetUuid); + + hostsWithSubnet.forEach(host -> { + DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(host).get(); + String interfaceName = subnetHostSpecificInfo.getInterfaceNameForLoopbackInHost(host, subnetUuid); + + try { + deleteSpecificLoopback(vppDataBroker, interfaceName); + } catch (LispConfigCommandFailedException e) { + e.printStackTrace(); + } + }); + + subnetHostSpecificInfo.clearSubnet(subnetUuid); + } + + public void handleEndpointDelete(AddressEndpointWithLocation addressEp) { + DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(addressEp).get(); + String hostId = loopbackManagerHelper.getHostName(addressEp).get(); + String portSubnetUuid = loopbackManagerHelper.getSubnet(addressEp); + String interfaceName = subnetHostSpecificInfo.getInterfaceNameForLoopbackInHost(hostId, portSubnetUuid); + if (subnetHostSpecificInfo.deletePortFromHostSubnetAndTriggerLoopbackDelete(hostId, portSubnetUuid)) { + GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(subnetUuidToGbpSubnetMapper.getSubnetInfo(portSubnetUuid), + "Invalid port!"); + long vni = getVni(addressEp.getTenant().getValue()); + try { + deleteSpecificLoopback(vppDataBroker, interfaceName); + deleteProxyArpRange(vppDataBroker, vni, gbpSubnetInfo, hostId); + } catch (LispConfigCommandFailedException e) { + LOG.warn("Loopback not deleted properly: {}", e.getMessage()); + } + } + } + + private void deleteSpecificLoopback(DataBroker vppDataBroker, String interfaceName) throws LispConfigCommandFailedException { + if (!GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker, + VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceName)), GbpNetconfTransaction.RETRY_COUNT)) { + throw new LispConfigCommandFailedException("Failed to delete Loopback interface!"); + } else { + LOG.debug("Deleted loopback interface!"); + } + } + + private void addProxyArpRange(DataBroker vppDataBroker, + long vrf, + GbpSubnet gbpSubnetInfo, + String hostName) throws LispConfigCommandFailedException { + Ipv4Prefix subnetPrefix = gbpSubnetInfo.getCidr().getIpv4Prefix(); + + Preconditions.checkNotNull(subnetPrefix, "Subnet CIDR found to be null for " + + "subnet uuid =" + gbpSubnetInfo.getId() + "!"); + + Pair startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix); + + if (!putArpRangesCommand(vppDataBroker, + vrf, + startAndEndAddress.getLeft(), + startAndEndAddress.getRight())) { + throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " + + gbpSubnetInfo.getId() + "!"); + } else { + LOG.debug("Configured proxy arp for range {} to {} on node : {}!", startAndEndAddress.getLeft(), + startAndEndAddress.getRight(), hostName); + } + } + + private void deleteProxyArpRange(DataBroker vppDataBroker, + long vrf, + GbpSubnet gbpSubnetInfo, + String hostName) throws LispConfigCommandFailedException { + Ipv4Prefix subnetPrefix = gbpSubnetInfo.getCidr().getIpv4Prefix(); + + Preconditions.checkNotNull(subnetPrefix, "Subnet CIDR found to be null for " + + "subnet uuid =" + gbpSubnetInfo.getId() + "!"); + + Pair startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix); + + if (!deleteArpRangesCommand(vppDataBroker, + vrf, + startAndEndAddress.getLeft(), + startAndEndAddress.getRight())) { + throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " + + gbpSubnetInfo.getId() + "!"); + } else { + LOG.debug("Removed proxy arp for range {} to {} on node : {}!", startAndEndAddress.getLeft(), + startAndEndAddress.getRight(), hostName); + } + } + + private boolean putArpRangesCommand(DataBroker vppDataBroker, long vrf, Ipv4Address start, Ipv4Address end) { + ProxyRangeCommand.ProxyRangeCommandBuilder builder = new ProxyRangeCommand.ProxyRangeCommandBuilder(); + builder.setOperation(General.Operations.PUT); + builder.setVrf(vrf); + builder.setStartAddress(start); + builder.setEndAddress(end); + + return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, + builder.build(), + GbpNetconfTransaction.RETRY_COUNT); + } + + private boolean deleteArpRangesCommand(DataBroker vppDataBroker, + long vrf, + Ipv4Address start, + Ipv4Address end) { + ProxyRangeCommand.ProxyRangeCommandBuilder builder = new ProxyRangeCommand.ProxyRangeCommandBuilder(); + builder.setOperation(General.Operations.DELETE); + builder.setVrf(vrf); + builder.setStartAddress(start); + builder.setEndAddress(end); + + return GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker, + builder.build(), + GbpNetconfTransaction.RETRY_COUNT); + } + + private long getVni(String tenantUuid) { + return neutronTenantToVniMapper.getVni(tenantUuid); + } + + private GbpSubnet getSubnetInfo(String subnetUuid) { + return subnetUuidToGbpSubnetMapper.getSubnetInfo(subnetUuid); + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/SubnetHostInfo.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/SubnetHostInfo.java new file mode 100644 index 000000000..62986f3a6 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/SubnetHostInfo.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback; + +import com.google.common.base.Preconditions; + +/** + * Created by Shakib Ahmed on 5/16/17. + */ +public class SubnetHostInfo { + private String interfaceName; + private int portCount; + + public SubnetHostInfo(String interfaceName) { + this.interfaceName = interfaceName; + this.portCount = 0; + } + + public String getInterfaceName() { + return interfaceName; + } + + public void setInterfaceName(String interfaceName) { + this.interfaceName = interfaceName; + } + + public void incrementPortCount() { + portCount++; + } + + public void decrementPortCount() { + Preconditions.checkArgument(portCount > 0, "No port to decrement"); + portCount--; + } + + public int incrementAndGetPortCount() { + incrementPortCount(); + return portCount; + } + + public int decrementAndGetPortCount() { + decrementPortCount(); + return portCount; + } + + public int getPortCount() { + return portCount; + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/HostVrfRoutingInformationMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/HostVrfRoutingInformationMapper.java new file mode 100644 index 000000000..97d8834ba --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/HostVrfRoutingInformationMapper.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017 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.lisp.mappers; + + +import com.google.common.base.Preconditions; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.RoutingInfo; + +import java.util.HashMap; + +/** + * Created by Shakib Ahmed on 5/4/17. + */ +public class HostVrfRoutingInformationMapper { + HashMap > mapper; + + private static final HostVrfRoutingInformationMapper INSTANCE = new HostVrfRoutingInformationMapper(); + + private HostVrfRoutingInformationMapper() { + mapper = new HashMap<>(); + } + + public static HostVrfRoutingInformationMapper getInstance() { + return INSTANCE; + } + + public void addRoutingVrfToHost(String hostId, long vrf, RoutingInfo routingInfo) { + HashMap routingInfoMapper = mapper.get(hostId); + + if (routingInfoMapper == null) { + routingInfoMapper = new HashMap<>(); + mapper.put(hostId, routingInfoMapper); + } + + routingInfoMapper.put(vrf, routingInfo); + } + + public boolean vrfExists(String hostId, long vrf) { + return mapper.containsKey(hostId) && mapper.get(hostId).containsKey(vrf); + } + + public String getProtocolName(String hostId, long vrf) { + Preconditions.checkArgument(vrfExists(hostId, vrf)); + + return mapper.get(hostId).get(vrf).getProtocolName(); + } + + public void addStaticRoute(String hostId, long vrf) { + HashMap routingInfoMapper = mapper.get(hostId); + + Preconditions.checkNotNull(routingInfoMapper, "Routing protocol not created, can't add route entry"); + + RoutingInfo routingInfo = routingInfoMapper.get(vrf); + + Preconditions.checkNotNull(routingInfoMapper, "VRF was not created for this host"); + + routingInfo.incrementCount(); + } + + public Long getEndPointCountInVrf(String hostId, long vrf) { + int count = 0; + + if (vrfExists(hostId, vrf)) { + count = mapper.get(hostId).get(vrf).getCount(); + } + return (long) (count + 1); + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/InterfaceNameToRouteInfoMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/InterfaceNameToRouteInfoMapper.java new file mode 100644 index 000000000..f227684cd --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/InterfaceNameToRouteInfoMapper.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 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.lisp.mappers; + +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Created by Shakib Ahmed on 5/26/17. + */ +public class InterfaceNameToRouteInfoMapper { + HashMap interfaceNameToStaticRouteMapper; + + public InterfaceNameToRouteInfoMapper() { + interfaceNameToStaticRouteMapper = new HashMap<>(); + } + + public boolean routeAlreadyExists(String interfaceName, Ipv4Address ip) { + StaticRouteInfoMapper staticRouteInfoMapper = interfaceNameToStaticRouteMapper.get(interfaceName); + + if (staticRouteInfoMapper == null) { + return false; + } + + return staticRouteInfoMapper.routeWithIpExists(ip); + } + + public void addRouteForInterface(String interfaceName, Ipv4Address ip, Long routeId) { + StaticRouteInfoMapper staticRouteInfoMapper = interfaceNameToStaticRouteMapper.get(interfaceName); + + if (staticRouteInfoMapper == null) { + staticRouteInfoMapper = new StaticRouteInfoMapper(); + interfaceNameToStaticRouteMapper.put(interfaceName, staticRouteInfoMapper); + } + + staticRouteInfoMapper.addIpRouteForInterface(ip, routeId); + } + + public List getRoutingIdsAssociatedWithInterface(String interfaceName) { + StaticRouteInfoMapper staticRouteInfoMapper = interfaceNameToStaticRouteMapper.get(interfaceName); + + return staticRouteInfoMapper == null ? new ArrayList<>() : staticRouteInfoMapper.getAllRoutingIds(); + } + + public void clearStaticRoutesForInterface(String interfaceName) { + interfaceNameToStaticRouteMapper.remove(interfaceName); + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/LoopbackHostSpecificInfoMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/LoopbackHostSpecificInfoMapper.java new file mode 100644 index 000000000..3d6302c1a --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/LoopbackHostSpecificInfoMapper.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2017 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.lisp.mappers; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import org.apache.commons.lang3.mutable.MutableInt; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.SubnetHostInfo; + +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Created by Shakib Ahmed on 4/26/17. + */ +public class LoopbackHostSpecificInfoMapper { + private HashMap> hostIdToSubnetMapper; + private Multimap subnetUuidToHostIdListMapper; + private HashMap hostIdToLoopbackCountMapper; + + public LoopbackHostSpecificInfoMapper() { + hostIdToSubnetMapper = new HashMap<>(); + subnetUuidToHostIdListMapper = ArrayListMultimap.create(); + hostIdToLoopbackCountMapper = new HashMap<>(); + } + + private HashMap getSubnetsOfHost(String hostName) { + return hostIdToSubnetMapper.get(hostName); + } + + public boolean loopbackAlreadyExists(String hostName, String subnetUuid) { + return hostIdToSubnetMapper.containsKey(hostName) && + hostIdToSubnetMapper.get(hostName).containsKey(subnetUuid); + } + + public void addLoopbackForHost(String hostName, String subnetUuid, String interfaceName, long vrf) { + putSubnetInfoOfAHost(hostName, subnetUuid, interfaceName, vrf); + subnetUuidToHostIdListMapper.put(subnetUuid, hostName); + } + + private void putSubnetInfoOfAHost(String hostId, String subnetUuid, String interfaceName, long vrf) { + HashMap subnetsOfAHost = getSubnetsOfHost(hostId); + MutableInt loopbackCount = getMutableIntAfterInitIfNecessary(hostId); + + loopbackCount.add(1); + + if (subnetsOfAHost == null) { + subnetsOfAHost = new HashMap<>(); + hostIdToSubnetMapper.put(hostId, subnetsOfAHost); + } + + SubnetHostInfo subnetHostInfo = new SubnetHostInfo(interfaceName); + subnetsOfAHost.put(subnetUuid, subnetHostInfo); + } + + private MutableInt getMutableIntAfterInitIfNecessary(String hostId) { + MutableInt loopbackCount = hostIdToLoopbackCountMapper.get(hostId); + + if (loopbackCount == null) { + loopbackCount = new MutableInt(); + loopbackCount.setValue(0); + hostIdToLoopbackCountMapper.put(hostId, loopbackCount); + } + return loopbackCount; + } + + public int getLoopbackCount(String hostName) { + MutableInt loopbackCount = getMutableIntAfterInitIfNecessary(hostName); + return loopbackCount.getValue(); + } + + public void clearSubnet(String subnetUuid) { + subnetUuidToHostIdListMapper.get(subnetUuid).forEach(hostId -> { + deleteParticularSubnetFromHost(hostId, subnetUuid); + }); + subnetUuidToHostIdListMapper.get(subnetUuid).clear(); + } + + private void deleteParticularSubnetFromHost(String hostId, String subnetUuid) { + hostIdToSubnetMapper.get(hostId).remove(subnetUuid); + } + + private void deleteHostFromSubnetMap(String subnetUuid, String hostId) { + subnetUuidToHostIdListMapper.get(subnetUuid).remove(hostId); + } + + public List getHostsWithSubnet(String subnetUuid) { + return subnetUuidToHostIdListMapper.get(subnetUuid).stream().collect(Collectors.toList()); + } + + public String getInterfaceNameForLoopbackInHost(String hostId, String subnetUuid) { + if (hostIdToSubnetMapper.get(hostId) != null) { + return hostIdToSubnetMapper.get(hostId).get(subnetUuid).getInterfaceName(); + } else { + return null; + } + } + + public int getPortCount(String hostId, String subnetUuid) { + if (hostIdToSubnetMapper.containsKey(hostId)) { + if (hostIdToSubnetMapper.get(hostId).containsKey(subnetUuid)) { + return hostIdToSubnetMapper.get(hostId).get(subnetUuid).getPortCount(); + } else { + return 0; + } + } else { + return 0; + } + } + + public void addNewPortInHostSubnet(String hostId, String subnetUuid) { + getSubnetsOfHost(hostId).get(subnetUuid).incrementPortCount(); + } + + public boolean deletePortFromHostSubnetAndTriggerLoopbackDelete(String hostId, String subnetUuid) { + if (getSubnetsOfHost(hostId).containsKey(subnetUuid)) { + int count = getSubnetsOfHost(hostId).get(subnetUuid).decrementAndGetPortCount(); + + if (count == 0) { + deleteParticularSubnetFromHost(hostId, subnetUuid); + } + + return count == 0; + } else { + return false; + } + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/StaticRouteInfoMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/StaticRouteInfoMapper.java new file mode 100644 index 000000000..a05060e1b --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/StaticRouteInfoMapper.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 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.lisp.mappers; + +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; + +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Created by Shakib Ahmed on 5/26/17. + */ +public class StaticRouteInfoMapper { + HashMap interfaceIpToRouteIdMapper; + + public StaticRouteInfoMapper() { + interfaceIpToRouteIdMapper = new HashMap<>(); + } + + public void addIpRouteForInterface(Ipv4Address ip, Long routingId) { + interfaceIpToRouteIdMapper.put(ip, routingId); + } + + public boolean routeWithIpExists(Ipv4Address ip) { + return interfaceIpToRouteIdMapper.containsKey(ip); + } + + public Long getRouteIdForIp(Ipv4Address ip) { + return interfaceIpToRouteIdMapper.get(ip); + } + + public List getAllRoutingIds() { + return interfaceIpToRouteIdMapper.entrySet() + .stream() + .map(ipv4AddressLongEntry -> ipv4AddressLongEntry.getValue()) + .collect(Collectors.toList()); + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/SubnetUuidToGbpSubnetMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/SubnetUuidToGbpSubnetMapper.java new file mode 100644 index 000000000..68b314658 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/SubnetUuidToGbpSubnetMapper.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. 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.lisp.mappers; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet; + +import java.util.HashMap; + +/** + * Created by Shakib Ahmed on 5/3/17. + */ +public class SubnetUuidToGbpSubnetMapper { + + private HashMap subnetInformation; + + private static SubnetUuidToGbpSubnetMapper INSTANCE = new SubnetUuidToGbpSubnetMapper(); + + private SubnetUuidToGbpSubnetMapper() { + subnetInformation = new HashMap<>(); + } + + public static SubnetUuidToGbpSubnetMapper getInstance() { + return INSTANCE; + } + + public void addSubnetInfo(String subnetUuid, GbpSubnet subnetInfo) { + subnetInformation.put(subnetUuid, subnetInfo); + } + + public GbpSubnet getSubnetInfo(String subnetUuid) { + return subnetInformation.get(subnetUuid); + } + + public void removeSubnetInfo(String subnetUuid) { + subnetInformation.remove(subnetUuid); + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/ConfigManagerHelper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/ConfigManagerHelper.java index 91185b7af..8b6240e47 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/ConfigManagerHelper.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/ConfigManagerHelper.java @@ -38,7 +38,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo 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.has.child.endpoints.ChildEndpoint; 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.MacAddressType; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType; @@ -276,10 +278,31 @@ public class ConfigManagerHelper { return locatorSet.iterator().next().getValue(); } + public Optional getInterfaceName(AddressEndpointWithLocation addedEp) { + ExternalLocationCase epLoc = resolveAndValidateLocation(addedEp); + String interfacePath = epLoc.getExternalNodeConnector(); + + return VppPathMapper.interfacePathToInterfaceName(interfacePath); + } + public HmacKey getDefaultHmacKey() { return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY); } + public String getPhysicalAddress(AddressEndpointWithLocation addressEp) { + String physicalAddress = null; + + List childEndpoints = addressEp.getChildEndpoint(); + for (ChildEndpoint childEndpoint : childEndpoints) { + if (childEndpoint.getAddressType().equals(MacAddressType.class)) { + physicalAddress = childEndpoint.getAddress(); + break; + } + } + return Preconditions.checkNotNull(physicalAddress, "Physical address not found " + + "in address endpoint: " + addressEp); + } + public Routing getRouting(long vrf) { return new RoutingBuilder().setIpv4VrfId(vrf).build(); } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/IpAddressUtil.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/IpAddressUtil.java new file mode 100644 index 000000000..7d135cf35 --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/IpAddressUtil.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 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.lisp.util; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.net.util.SubnetUtils; +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; + +/** + * Created by Shakib Ahmed on 5/3/17. + */ +public class IpAddressUtil { + + public static Pair getStartAndEndIp(Ipv4Prefix ipv4Prefix) { + SubnetUtils subnetUtils = new SubnetUtils(ipv4Prefix.getValue()); + SubnetUtils.SubnetInfo prefixSubnetInfo = subnetUtils.getInfo(); + Ipv4Address lowIp = new Ipv4Address(prefixSubnetInfo.getLowAddress()); + Ipv4Address highIp = new Ipv4Address(prefixSubnetInfo.getHighAddress()); + return new ImmutablePair<>(lowIp, highIp); + } +} \ No newline at end of file diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java index f3d9331a3..a42835acd 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java @@ -28,7 +28,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand; import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil; import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatUtil; import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager; @@ -102,19 +103,21 @@ public final class ForwardingManager { private final NatManager natManager; private final RoutingManager routingManager; private final LispStateManager lispStateManager; - private final BviManager bviManager; + private final LoopbackManager loopbackManager; + private final FlatOverlayManager flatOverlayManager; private final DataBroker dataBroker; public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull AclManager aclManager, - @Nonnull NatManager natManager, @Nonnull RoutingManager routingManager, @Nonnull BridgeDomainManager bdManager, - @Nonnull LispStateManager lispStateManager, @Nonnull BviManager bviManager, - @Nonnull DataBroker dataBroker) { + @Nonnull NatManager natManager, @Nonnull RoutingManager routingManager, @Nonnull BridgeDomainManager bdManager, + @Nonnull LispStateManager lispStateManager, @Nonnull LoopbackManager loopbackManager, @Nonnull FlatOverlayManager flatOverlayManager, + @Nonnull DataBroker dataBroker) { this.ifaceManager = Preconditions.checkNotNull(ifaceManager); this.bdManager = Preconditions.checkNotNull(bdManager); this.natManager = Preconditions.checkNotNull(natManager); this.routingManager = Preconditions.checkNotNull(routingManager); this.lispStateManager = Preconditions.checkNotNull(lispStateManager); - this.bviManager = Preconditions.checkNotNull(bviManager); + this.loopbackManager = Preconditions.checkNotNull(loopbackManager); + this.flatOverlayManager = Preconditions.checkNotNull(flatOverlayManager); this.dataBroker = Preconditions.checkNotNull(dataBroker); this.aclManager = Preconditions.checkNotNull(aclManager); } @@ -205,6 +208,10 @@ public final class ForwardingManager { if (ConfigUtil.getInstance().isLispOverlayEnabled()) { lispStateManager.configureEndPoint(rEp); + if (ConfigUtil.getInstance().isL3FlatEnabled()) { + flatOverlayManager.configureEndpointForFlatOverlay(rEp); + loopbackManager.createSimpleLoopbackIfNeeded(rEp); + } } ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp); @@ -229,7 +236,7 @@ public final class ForwardingManager { LOG.debug("Interface added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp); if (ConfigUtil.getInstance().isLispOverlayEnabled()) { - bviManager.createBviIfNecessary(rEp, l2FloodDomain); + loopbackManager.createBviLoopbackIfNeeded(rEp, l2FloodDomain); } } catch (InterruptedException | ExecutionException e) { @@ -275,6 +282,12 @@ public final class ForwardingManager { try { if (ConfigUtil.getInstance().isLispOverlayEnabled()) { lispStateManager.deleteLispConfigurationForEndpoint(rEp); + loopbackManager.handleEndpointDelete(rEp); + + if (ConfigUtil.getInstance().isL3FlatEnabled()) { + flatOverlayManager.handleEndpointDeleteForFlatOverlay(rEp); + } + } ifaceManager.deleteBridgeDomainFromInterface(rEp).get(); LOG.debug("bridge-domain was deleted from interface for endpoint {}", rEp); diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/GbpNetconfTransaction.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/GbpNetconfTransaction.java index b054a000d..ca2922d68 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/GbpNetconfTransaction.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/GbpNetconfTransaction.java @@ -53,6 +53,23 @@ public class GbpNetconfTransaction { return result; } + /*** + * Netconf wrapper for merge operation on a Netconf Device + * @param mountpoint netconf device + * @param iid path for Data to be merged to + * @param data data to be merged + * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails + * @param data type + * @return true if transaction is successful, false otherwise + */ + public static boolean netconfSyncedMerge(@Nonnull final DataBroker mountpoint, + @Nonnull final InstanceIdentifier iid, @Nonnull final T data, byte retryCounter) { + VbdNetconfTransaction.REENTRANT_LOCK.lock(); + boolean result = merge(mountpoint, iid, data, retryCounter); + VbdNetconfTransaction.REENTRANT_LOCK.unlock(); + return result; + } + /*** * Netconf wrapper method for synced requests for write operation on a Netconf Device * @param mountpoint netconf device @@ -193,6 +210,39 @@ public class GbpNetconfTransaction { } } + /** + * Merge data to remote device. Transaction is restarted if failed + * + * @param mountpoint to access remote device + * @param iid data identifier + * @param data to merge + * @param retryCounter number of attempts + * @param generic data type. Has to be child of {@link DataObject} + * @return true if transaction is successful, false otherwise + */ + private static boolean merge(final DataBroker mountpoint, final InstanceIdentifier iid, + final T data, byte retryCounter) { + LOG.trace("Netconf MERGE transaction started. RetryCounter: {}", retryCounter); + Preconditions.checkNotNull(mountpoint); + final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction(); + try { + rwTx.merge(LogicalDatastoreType.CONFIGURATION, iid, data, true); + final CheckedFuture futureTask = rwTx.submit(); + futureTask.get(); + LOG.trace("Netconf MERGE transaction done for {}", iid); + return true; + } catch (Exception e) { + // Retry + if (retryCounter > 0) { + LOG.warn("Netconf MERGE transaction failed to {}. Restarting transaction ... ", e.getMessage()); + return write(mountpoint, iid, data, --retryCounter); + } else { + LOG.warn("Netconf MERGE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e); + return false; + } + } + } + /** * Use {@link AbstractLispCommand} to put data into netconf transaction and submit. Transaction is restarted if failed * diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java index 95e0bc39f..a20f03cb5 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java @@ -13,9 +13,14 @@ 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.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; 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.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatConfig; 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; @@ -58,6 +63,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.bridge.domains.state.BridgeDomainKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppAcl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyRanges; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRange; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRangeKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; @@ -199,4 +207,26 @@ public class VppIidFactory { return InstanceIdentifier.builder(Lisp.class) .child(LispFeatureData.class).build(); } + + public static InstanceIdentifier getProxyRangeIid(Long vrf, + Ipv4Address startAddress, + Ipv4Address endAddress) { + return InstanceIdentifier.builder(ProxyRanges.class) + .child(ProxyRange.class, new ProxyRangeKey(endAddress, startAddress, vrf)).build(); + } + + public static InstanceIdentifier getRoutingIid(InterfaceKey interfaceKey) { + return getInterfaceIID(interfaceKey) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315 + .interfaces._interface.Routing.class); + } + + public static InstanceIdentifier getNeighborIid(InterfaceKey interfaceKey, NeighborKey neighborKey) { + return getInterfaceIID(interfaceKey) + .augmentation(Interface1.class) + .child(Ipv4.class) + .child(Neighbor.class, neighborKey); + } } diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImplTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImplTest.java index 541f2acdd..f6d6fdffd 100644 --- a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImplTest.java +++ b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImplTest.java @@ -24,7 +24,8 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager; @@ -109,10 +110,11 @@ public class BridgeDomainManagerImplTest extends CustomDataBrokerTest { final NatManager natManager = Mockito.mock(NatManager.class); final RoutingManager routingManager = Mockito.mock(RoutingManager.class); final LispStateManager lispStateManager = Mockito.mock(LispStateManager.class); - final BviManager bviManager = Mockito.mock(BviManager.class); + final FlatOverlayManager flatOverlayManager = Mockito.mock(FlatOverlayManager.class); + final LoopbackManager loopbackManager = Mockito.mock(LoopbackManager.class); final ForwardingManager fwManager = new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bridgeDomainManager, - lispStateManager, bviManager, dataBroker); + lispStateManager, loopbackManager, flatOverlayManager, dataBroker); fwManager.setTimer((byte) 1); } diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManagerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManagerTest.java index 1ae6f5f09..53416e2ed 100644 --- a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManagerTest.java +++ b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManagerTest.java @@ -24,7 +24,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.DtoFactory; import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper; import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager; @@ -72,7 +73,9 @@ public class ForwardingManagerTest extends CustomDataBrokerTest { @Mock private LispStateManager lispStateManager; @Mock - private BviManager bviManager; + private FlatOverlayManager flatOverlayManager; + @Mock + private LoopbackManager loopbackManager; private ForwardingManager fwdManager; @@ -80,7 +83,7 @@ public class ForwardingManagerTest extends CustomDataBrokerTest { public void init() { fwdManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, lispStateManager, - bviManager, getDataBroker()); + loopbackManager, flatOverlayManager, getDataBroker()); } @Override diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java index b1201c907..1f28549ff 100644 --- a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java +++ b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java @@ -29,7 +29,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationProvider; import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager; -import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager; @@ -89,7 +90,8 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest { private NatManager natManager; private RoutingManager routingManager; private LispStateManager lispStateManager; - private BviManager bviManager; + private LoopbackManager loopbackManager; + private FlatOverlayManager flatOverlayManager; private VppRendererPolicyManager vppRendererPolicyManager; @Override @@ -113,9 +115,10 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest { routingManager = new RoutingManager(dataBroker, mountedDataProviderMock); bdManager = new BridgeDomainManagerImpl(mountPointDataBroker); lispStateManager = new LispStateManager(mountedDataProviderMock); - bviManager = new BviManager(mountedDataProviderMock); + loopbackManager = new LoopbackManager(mountedDataProviderMock); + flatOverlayManager = new FlatOverlayManager(mountedDataProviderMock); fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, - lispStateManager, bviManager, dataBroker); + lispStateManager, loopbackManager, flatOverlayManager, dataBroker); vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker); fwManager.setTimer((byte) 1); } -- 2.36.6