From 28208ac2b1b9e068c51eee79cf1bfedc6a818195 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 12 Apr 2016 10:13:37 +0200 Subject: HONEYCOMB-9: Migrate Interface listener Change-Id: Iffde1ee21b749a8c8efa96c243f7f8bb0811b4c7 Signed-off-by: Maros Marsalek --- .../v3po/interfaces/EthernetCustomizer.java | 70 +++++++ .../v3po/interfaces/InterfaceCustomizer.java | 72 +++++++ .../translate/v3po/interfaces/L2Customizer.java | 179 ++++++++++++++++++ .../v3po/interfaces/RoutingCustomizer.java | 115 +++++++++++ .../v3po/interfaces/VppInterfaceCustomizer.java | 210 +++++++++++++++++++++ .../translate/v3po/interfaces/VxlanCustomizer.java | 112 +++++++++++ .../v3po/interfaces/ip/Interface1Customizer.java | 60 ++++++ .../v3po/interfaces/ip/Ipv4Customizer.java | 153 +++++++++++++++ .../v3po/interfaces/ip/Ipv6Customizer.java | 66 +++++++ .../v3po/translate/v3po/utils/V3poUtils.java | 78 ++++++++ .../translate/v3po/vpp/BridgeDomainCustomizer.java | 15 +- 11 files changed, 1118 insertions(+), 12 deletions(-) create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java (limited to 'v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java new file mode 100644 index 000000000..69ff63137 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Ethernet; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EthernetCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(EthernetCustomizer.class); + + public EthernetCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getEthernet()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ethernet dataAfter, @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ethernet dataBefore, @Nonnull final Ethernet dataAfter, + @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ethernet dataBefore, @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration delete {}", id); + + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java new file mode 100644 index 000000000..6b91e2e0a --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import java.util.List; +import javax.annotation.Nonnull; +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.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.vppjapi.vppApi; + +/** + * Ietf interface write customizer that only caches interface objects for child writers + */ +public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterCustomizer { + + public static final String IFC_AFTER_CTX = InterfaceCustomizer.class.toString() + "ifcAfter"; + public static final String IFC_BEFORE_CTX = InterfaceCustomizer.class.toString() + "ifcBefore"; + + public InterfaceCustomizer(final vppApi vppApi) { + super(vppApi); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface dataAfter, + @Nonnull final Context writeContext) { + writeContext.put(IFC_AFTER_CTX, dataAfter); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface dataBefore, + @Nonnull final Interface dataAfter, + @Nonnull final Context writeContext) { + writeContext.put(IFC_BEFORE_CTX, dataBefore); + writeContext.put(IFC_AFTER_CTX, dataAfter); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface dataBefore, + @Nonnull final Context writeContext) { + writeContext.put(IFC_BEFORE_CTX, dataBefore); + } + + @Nonnull + @Override + public List extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return ((Interfaces) parentData).getInterface(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java new file mode 100644 index 000000000..e596f8fbf --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.Interconnection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBased; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.XconnectBased; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class); + + public L2Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getL2()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2 dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + + final int swIfc = getSwIfc(ifc); + try { + setL2(id, swIfc, ifc, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Write of L2 failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2 dataBefore, + @Nonnull final L2 dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + final int swIfc = getSwIfc(ifcBefore); + // TODO handle update properly (if possible) + try { + setL2(id, swIfc, ifcAfter, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of L2 failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + private int getSwIfc(final Interface ifcBefore) { + int swIfcIndex = getVppApi().swIfIndexFromName(ifcBefore.getName()); + checkArgument(swIfcIndex != -1, "Interface %s does not exist", ifcBefore.getName()); + return swIfcIndex; + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2 dataBefore, + @Nonnull final Context writeContext) { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + final int swIfc = getSwIfc(ifcBefore); + // TODO implement delete (if possible) + } + + private void setL2(final InstanceIdentifier id, final int swIfIndex, final Interface ifc, final L2 vppL2) + throws VppApiInvocationException, WriteFailedException { + LOG.debug("Setting L2 for interface: %s", ifc.getName()); + // Nothing besides interconnection here + setInterconnection(id, swIfIndex, ifc, vppL2); + } + + private void setInterconnection(final InstanceIdentifier id, final int swIfIndex, final Interface ifc, + final L2 vppL2) + throws VppApiInvocationException, WriteFailedException { + Interconnection ic = vppL2.getInterconnection(); + if (ic instanceof XconnectBased) { + setXconnectBasedL2(swIfIndex, ifc, (XconnectBased) ic); + } else if (ic instanceof BridgeBased) { + setBridgeBasedL2(swIfIndex, ifc, (BridgeBased) ic); + } else { + // FIXME how does choice extensibility work + // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject + // FIXME we might need a choice customizer + // THis choice is already from augment, so its probably not possible to augment augmented choice + LOG.error("Unable to handle Interconnection of type {}", ic.getClass()); + throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass()); + } + } + + private void setBridgeBasedL2(final int swIfIndex, final Interface ifc, final BridgeBased bb) + throws VppApiInvocationException { + + LOG.debug("Setting bridge based interconnection(bridge-domain=%s) for interface: %s", + bb.getBridgeDomain(), ifc.getName()); + + String bdName = bb.getBridgeDomain(); + int bdId = getVppApi().bridgeDomainIdFromName(bdName); + checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist", + ifc.getName(), bdName); + + byte bvi = bb.isBridgedVirtualInterface() + ? (byte) 1 + : (byte) 0; + byte shg = bb.getSplitHorizonGroup().byteValue(); + + final int ctxId = getVppApi().swInterfaceSetL2Bridge(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + + if (rv < 0) { + LOG.warn("Failed to update bridge based interconnection flags for: {}, interconnection: {}", ifc.getName(), + bb); + throw new VppApiInvocationException("swInterfaceSetL2Bridge", ctxId, rv); + } else { + LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifc.getName(), + bb); + } + } + + private void setXconnectBasedL2(final int swIfIndex, final Interface ifc, final XconnectBased ic) + throws VppApiInvocationException { + + String outSwIfName = ic.getXconnectOutgoingInterface(); + LOG.debug("Setting xconnect based interconnection(outgoing ifc=%s) for interface: %s", outSwIfName, + ifc.getName()); + + int outSwIfIndex = getVppApi().swIfIndexFromName(outSwIfName); + checkArgument(outSwIfIndex > 0, + "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist", + ifc.getName(), outSwIfIndex); + + int ctxId = getVppApi().swInterfaceSetL2Xconnect(swIfIndex, outSwIfIndex, (byte) 1 /* enable */); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + + if (rv < 0) { + LOG.warn("Failed to update xconnect based interconnection flags for: {}, interconnection: {}", + ifc.getName(), ic); + throw new VppApiInvocationException("swInterfaceSetL2Xconnect", ctxId, rv); + } else { + LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifc.getName(), + ic); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java new file mode 100644 index 000000000..8d930d80c --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Routing; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(RoutingCustomizer.class); + + public RoutingCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getRouting()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Routing dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException.CreateFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + + try { + setRouting(ifc.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of Routing failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Routing dataBefore, @Nonnull final Routing dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException.UpdateFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + try { + // TODO handle updates properly + setRouting(ifcAfter.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of Routing failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Routing dataBefore, @Nonnull final Context writeContext) { + // TODO implement delete + } + + private void setRouting(final String name, final Routing rt) throws VppApiInvocationException { + final int swIfc = getSwIfc(name); + LOG.debug("Setting routing for interface: {}, {}. Routing: {}", name, swIfc, rt); + + int vrfId = (rt != null) + ? rt.getVrfId().intValue() + : 0; + + if (vrfId != 0) { + final int ctxId = getVppApi().swInterfaceSetTable(swIfc, (byte) 0, /* isIpv6 */ vrfId); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.debug("Failed to set routing for interface: {}, {}, vxlan: {}", name, swIfc, rt); + throw new VppApiInvocationException("swInterfaceSetTable", ctxId, rv); + } else { + LOG.debug("Routing set successfully for interface: {}, {}, routing: {}", name, swIfc, rt); + } + } + } + + private int getSwIfc(final String name) { + int swIfcIndex = getVppApi().swIfIndexFromName(name); + checkArgument(swIfcIndex != -1, "Interface %s does not exist", name); + return swIfcIndex; + } + +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java new file mode 100644 index 000000000..3ea3f9743 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VppInterfaceCustomizer extends VppApiCustomizer + implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(VppInterfaceCustomizer.class); + + public VppInterfaceCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract( + @Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface) parentData).getAugmentation(VppInterfaceAugmentation.class)); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VppInterfaceAugmentation dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + try { + setInterface(id, ifc, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of VppInterfaceAugment failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VppInterfaceAugmentation dataBefore, + @Nonnull final VppInterfaceAugmentation dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException.UpdateFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + try { + updateInterface(id, ifc, dataBefore, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of VppInterfaceAugment failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VppInterfaceAugmentation dataBefore, + @Nonnull final Context writeContext) { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + LOG.info("Deleting interface: {}, type: {}", ifcBefore.getName(), ifcBefore.getType().getSimpleName()); + + if (ifcBefore.getType().isAssignableFrom(EthernetCsmacd.class)) { + LOG.error("Interface {}, type: {} cannot be deleted", + ifcBefore.getName(), ifcBefore.getType().getSimpleName()); + + /* FIXME: Add additional interface types here. + * + * } else if (swIf.getType().isAssignableFrom(*.class)) { + */ + + } + } + + + private void updateInterface(final InstanceIdentifier id, final Interface swIf, + final VppInterfaceAugmentation dataBefore, + final VppInterfaceAugmentation dataAfter) throws VppApiInvocationException { + LOG.info("Updating interface {}, type: {}", swIf.getName(), swIf.getType().getSimpleName()); + LOG.debug("Updating interface {}", swIf); + + Class ifType = checkNotNull(swIf.getType(), "Interface type missing for %s", swIf); + String swIfName = swIf.getName(); + int swIfIndex = getVppApi().swIfIndexFromName(swIfName); + checkArgument(swIfIndex != -1, "Updating non-existing vpp interface: %s", swIfName); + + // TODO handle updates properly + + if (VxlanTunnel.class.isAssignableFrom(ifType)) { + updateVxlanTunnelInterface(swIf); + } else if (EthernetCsmacd.class.isAssignableFrom(ifType)) { + updateEthernetCsmacdInterface(swIf, swIfName, swIfIndex); + } + } + + + private void setInterface(final InstanceIdentifier id, final Interface swIf, + final VppInterfaceAugmentation dataAfter) + throws VppApiInvocationException, WriteFailedException { + LOG.info("Setting interface {}, type: {}", swIf.getName(), swIf.getType().getSimpleName()); + LOG.debug("Setting interface {}", swIf); + + Class ifType = checkNotNull(swIf.getType(), "Interface type missing for %s", swIf); + String swIfName = swIf.getName(); + int swIfIndex = getVppApi().swIfIndexFromName(swIfName); + checkArgument(swIfIndex == -1, "Creating already-existing vpp interface: %s", swIfName); + + if (VxlanTunnel.class.isAssignableFrom(ifType)) { + createVxlanTunnelInterface(swIf, swIfName); + } else if (EthernetCsmacd.class.isAssignableFrom(ifType)) { + createEthernetCsmacdInterface(id, swIfName, dataAfter); + } + } + + private void createVxlanTunnelInterface(final Interface swIf, final String swIfName) + throws VppApiInvocationException { + LOG.debug("Creating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); + + // FIXME, Vxlan child writer needs to be handled before this is + int newSwIfIndex = getVppApi().swIfIndexFromName(swIfName); + + setInterfaceFlags(swIfName, newSwIfIndex, swIf.isEnabled() + ? (byte) 1 + : (byte) 0); + setDescription(swIf); + } + + private void updateVxlanTunnelInterface(final Interface swIf) { + LOG.debug("Updating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); + + // TODO handle + } + + private void createEthernetCsmacdInterface(final InstanceIdentifier id, + final String swIfName, final VppInterfaceAugmentation dataAfter) throws WriteFailedException { + LOG.warn("Unable to create interface: {}, type: {}", swIfName, EthernetCsmacd.class); + throw new WriteFailedException.CreateFailedException(id, dataAfter); + } + + private void updateEthernetCsmacdInterface(final Interface swIf, + final String swIfName, final int swIfIndex) + throws VppApiInvocationException { + LOG.debug("Updating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); + byte enabled = swIf.isEnabled() + ? (byte) 1 + : (byte) 0; + setInterfaceFlags(swIfName, swIfIndex, enabled); + setDescription(swIf); + } + + private void setInterfaceFlags(final String swIfName, final int swIfIndex, final byte enabled) + throws VppApiInvocationException { + int ctxId = getVppApi().swInterfaceSetFlags(swIfIndex, enabled, enabled, (byte) 0 /* deleted */); + + LOG.debug("Updating interface flags for: {}, index: {}, enabled: {}, ctxId: {}", swIfName, swIfIndex, + enabled, ctxId); + + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.warn("Failed to update interface flags for: {}, index: {}, enabled: {}, ctxId: {}", swIfName, swIfIndex, + enabled, ctxId); + throw new VppApiInvocationException("swInterfaceSetFlags", ctxId, rv); + } else { + LOG.debug("Interface flags updated successfully for: {}, index: {}, enabled: {}, ctxId: {}", + swIfName, swIfIndex, enabled, ctxId); + } + } + + private void setDescription(final Interface swIf) { + if (swIf.getDescription() != null) { + getVppApi().setInterfaceDescription(swIf.getName(), swIf.getDescription()); + } else { + getVppApi().setInterfaceDescription(swIf.getName(), ""); + } + } + +} + diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java new file mode 100644 index 000000000..2b2774ece --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +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.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VxlanCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class); + + + public VxlanCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getVxlan()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Vxlan dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException.CreateFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + try { + createVxlanTunnel(ifc.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Write of Vxlan failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Vxlan dataBefore, + @Nonnull final Vxlan dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException.UpdateFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + // TODO handle update in a better way + try { + createVxlanTunnel(ifcAfter.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of L2 failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Vxlan dataBefore, + @Nonnull final Context writeContext) { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + // TODO handle delete + } + + private void createVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException { + Ipv4Address srcAddress = vxlan.getSrc(); + Ipv4Address dstAddress = vxlan.getDst(); + + int srcAddr = V3poUtils.parseIp(srcAddress.getValue()); + int dstAddr = V3poUtils.parseIp(dstAddress.getValue()); + int encapVrfId = vxlan.getEncapVrfId().intValue(); + int vni = vxlan.getVni().getValue().intValue(); + + LOG.debug("Setting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan); + int ctxId = getVppApi().vxlanAddDelTunnel((byte) 1 /* is add */, srcAddr, dstAddr, encapVrfId, -1, vni); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.debug("Failed to set vxlan tunnel for interface: {}, vxlan: {}", swIfName, vxlan); + throw new VppApiInvocationException("vxlanAddDelTunnel", ctxId, rv); + } else { + LOG.debug("Vxlan tunnel set successfully for: {}, vxlan: {}", swIfName, vxlan); + // FIXME avoid this dump just to fill cache in vpp-japi + // refresh interfaces to be able to get ifIndex + getVppApi().swInterfaceDump((byte) 1, V3poUtils.IFC_TYPES.inverse().get(VxlanTunnel.class).getBytes()); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java new file mode 100644 index 000000000..9f3584908 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces.ip; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import javax.annotation.Nonnull; +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.ip.rev140616.Interface1; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class Interface1Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + public Interface1Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface) parentData).getAugmentation(Interface1.class)); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface1 dataAfter, @Nonnull final Context writeContext) { + + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface1 dataBefore, @Nonnull final Interface1 dataAfter, + @Nonnull final Context writeContext) { + + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface1 dataBefore, @Nonnull final Context writeContext) { + + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java new file mode 100644 index 000000000..08974fe68 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces.ip; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.InterfaceCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +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.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.Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.Subnet; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.Netmask; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(Ipv4Customizer.class); + + public Ipv4Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface1) parentData).getIpv4()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv4 dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + + try { + setIpv4(id, ifc.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Create of Ipv4 failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv4 dataBefore, @Nonnull final Ipv4 dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + // TODO handle update in a better way + try { + setIpv4(id, ifcAfter.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of Ipv4 failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv4 dataBefore, @Nonnull final Context writeContext) { + // TODO implement delete + } + + private void setIpv4(final InstanceIdentifier id, final String name, final Ipv4 ipv4) + throws WriteFailedException, VppApiInvocationException { + final int swIfc = getSwIfc(name); + + for (Address ipv4Addr : ipv4.getAddress()) { + Subnet subnet = ipv4Addr.getSubnet(); + + if (subnet instanceof PrefixLength) { + setPrefixLengthSubnet(name, swIfc, ipv4Addr, (PrefixLength) subnet); + } else if (subnet instanceof Netmask) { + setNetmaskSubnet(); + } else { + // FIXME how does choice extensibility work + // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject + // FIXME we might need a choice customizer + // THis choice is already from augment, so its probably not possible to augment augmented choice + LOG.error("Unable to handle subnet of type {}", subnet.getClass()); + throw new WriteFailedException(id, "Unable to handle subnet of type " + subnet.getClass()); + } + } + } + + private void setNetmaskSubnet() { + // FIXME + throw new UnsupportedOperationException("Unimplemented"); + } + + private void setPrefixLengthSubnet(final String name, final int swIfc, final Address ipv4Addr, + final PrefixLength subnet) throws VppApiInvocationException { + Short plen = subnet.getPrefixLength(); + LOG.debug("Setting Subnet(prefix-length) for interface: {}, {}. Subnet: {}, Ipv4: {}", name, swIfc, subnet, + ipv4Addr); + + byte[] addr = V3poUtils.ipv4AddressNoZoneToArray(ipv4Addr.getIp()); + + checkArgument(plen > 0, "Invalid length"); + checkNotNull(addr, "Null address"); + + final int ctxId = getVppApi().swInterfaceAddDelAddress(swIfc, (byte) 1 /* isAdd */, (byte) 0 /* isIpv6 */, + (byte) 0 /* delAll */, plen.byteValue(), addr); + + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.warn("Failed to set Subnet(prefix-length) for interface: {}, {}, Subnet: {}, Ipv4: {}", name, swIfc, + subnet, ipv4Addr); + throw new VppApiInvocationException("swInterfaceAddDelAddress", ctxId, rv); + } else { + LOG.debug("Subnet(prefix-length) set successfully for interface: {}, {}, Subnet: {}, Ipv4: {}", name, + swIfc, subnet, ipv4Addr); + } + } + + + private int getSwIfc(final String name) { + int swIfcIndex = getVppApi().swIfIndexFromName(name); + checkArgument(swIfcIndex != -1, "Interface %s does not exist", name); + return swIfcIndex; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java new file mode 100644 index 000000000..3798f891a --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces.ip; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import javax.annotation.Nonnull; +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.Ipv6; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Ipv6Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(Ipv6Customizer.class); + + public Ipv6Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface1) parentData).getIpv6()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv6 dataAfter, @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv6 dataBefore, @Nonnull final Ipv6 dataAfter, + @Nonnull final Context writeContext) { + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv6 dataBefore, @Nonnull final Context writeContext) { + LOG.warn("Unsupported, ignoring configuration delete {}", id); + // TODO + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java new file mode 100644 index 000000000..18a8103cc --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.utils; + +import com.google.common.base.Splitter; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.SoftwareLoopback; +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.InterfaceType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; +import org.openvpp.vppjapi.vppApi; + +public final class V3poUtils { + + // TODO move to vpp-translate-utils + + public static final int RESPONSE_NOT_READY = -77; + public static final int RELEASE = 1; + public static final Splitter DOT_SPLITTER = Splitter.on('.'); + public static final BiMap> IFC_TYPES = HashBiMap.create(); + static { + V3poUtils.IFC_TYPES.put("vxlan", VxlanTunnel.class); + V3poUtils.IFC_TYPES.put("lo", SoftwareLoopback.class); + V3poUtils.IFC_TYPES.put("Ether", EthernetCsmacd.class); + // TODO missing types below +// V3poUtils.IFC_TYPES.put("l2tpv3_tunnel", EthernetCsmacd.class); +// V3poUtils.IFC_TYPES.put("tap", EthernetCsmacd.class); + } + + private V3poUtils() {} + + public static int waitForResponse(final int ctxId, final vppApi vppApi) { + int rv; + while ((rv = vppApi.getRetval(ctxId, RELEASE)) == RESPONSE_NOT_READY) { + // TODO limit attempts + } + return rv; + } + + public static int parseIp(final String address) { + int result = 0; + + // iterate over each octet + for (String part : DOT_SPLITTER.split(address)) { + // shift the previously parsed bits over by 1 byte + result = result << 8; + // set the low order bits to the current octet + result |= Integer.parseInt(part); + } + return result; + } + + public static byte[] ipv4AddressNoZoneToArray(final Ipv4AddressNoZone ipv4Addr) { + byte[] retval = new byte[4]; + String[] dots = ipv4Addr.getValue().split("\\."); + + for (int d = 3; d >= 0; d--) { + retval[d] = (byte) (Short.parseShort(dots[3 - d]) & 0xff); + } + return retval; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java index ffbc95beb..c69f2ef0a 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java @@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkState; import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -41,8 +42,6 @@ public class BridgeDomainCustomizer private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class); private static final byte ADD_OR_UPDATE_BD = (byte) 1; - private static final int RESPONSE_NOT_READY = -77; - private static final int RELEASE = 1; public BridgeDomainCustomizer(final org.openvpp.vppjapi.vppApi api) { super(api); @@ -55,14 +54,6 @@ public class BridgeDomainCustomizer return ((BridgeDomains) parentData).getBridgeDomain(); } - private int waitForResponse(final int ctxId) { - int rv; - while ((rv = getVppApi().getRetval(ctxId, RELEASE)) == RESPONSE_NOT_READY) { - // TODO limit attempts - } - return rv; - } - private int addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd) { byte flood = booleanToByte(bd.isFlood()); byte forward = booleanToByte(bd.isForward()); @@ -71,7 +62,7 @@ public class BridgeDomainCustomizer byte arpTerm = booleanToByte(bd.isArpTermination()); int ctxId = getVppApi().bridgeDomainAddDel(bdId, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); - return waitForResponse(ctxId); + return V3poUtils.waitForResponse(ctxId, getVppApi()); } @Override @@ -111,7 +102,7 @@ public class BridgeDomainCustomizer (byte) 0 /* arpTerm */, (byte) 0 /* isAdd */); - int rv = waitForResponse(ctxId); + int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); checkState(rv >= 0, "Bridge domain delete failed. Return code: %s", rv); LOG.debug("Bridge domain {} deleted as {} successfully", bdName, bdId); -- cgit 1.2.3-korg