diff options
author | 2016-05-10 16:35:16 +0200 | |
---|---|---|
committer | 2016-05-11 09:21:50 +0200 | |
commit | e8b97ff12ea9aa475f38fa6c5eb20c997c2c54ed (patch) | |
tree | 09ac49946b93b1cbb66eb59c989f80a6ad49449b /v3po/v3po2vpp/src/main/java/io | |
parent | 44348596ff0c675bf3b799f88288111d92d771e6 (diff) |
HONEYCOMB-36: vhost user interfaces CRUD support
Change-Id: I1c16cf71fa450fe5079b4af8b1e24bdc921a6e82
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'v3po/v3po2vpp/src/main/java/io')
6 files changed, 319 insertions, 1 deletions
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizer.java new file mode 100644 index 000000000..40669761d --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizer.java @@ -0,0 +1,180 @@ +/* + * 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 com.google.common.base.Preconditions; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +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 java.util.concurrent.CompletionStage; +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.VhostUserRole; +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.VhostUser; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.CreateVhostUserIf; +import org.openvpp.jvpp.dto.CreateVhostUserIfReply; +import org.openvpp.jvpp.dto.DeleteVhostUserIf; +import org.openvpp.jvpp.dto.DeleteVhostUserIfReply; +import org.openvpp.jvpp.dto.ModifyVhostUserIf; +import org.openvpp.jvpp.dto.ModifyVhostUserIfReply; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Writer Customizer responsible for passing vhost user interface CRD operations to VPP + */ +public class VhostUserCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer<VhostUser> { + + private static final Logger LOG = LoggerFactory.getLogger(VhostUserCustomizer.class); + private final NamingContext interfaceContext; + + public VhostUserCustomizer(@Nonnull final FutureJVpp vppApi, @Nonnull final NamingContext interfaceContext) { + super(vppApi); + this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); + } + + @Nonnull + @Override + public Optional<VhostUser> extract(@Nonnull final InstanceIdentifier<VhostUser> currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getVhostUser()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<VhostUser> id, + @Nonnull final VhostUser dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException.CreateFailedException { + try { + createVhostUserIf(id.firstKeyOf(Interface.class).getName(), dataAfter); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + private void createVhostUserIf(final String swIfName, final VhostUser vhostUser) throws VppApiInvocationException { + LOG.debug("Creating vhost user interface: name={}, vhostUser={}", swIfName, vhostUser); + final CompletionStage<CreateVhostUserIfReply> createVhostUserIfReplyCompletionStage = + getFutureJVpp().createVhostUserIf(getCreateVhostUserIfRequest(vhostUser)); + + final CreateVhostUserIfReply reply = + V3poUtils.getReply(createVhostUserIfReplyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { + LOG.debug("Failed to create vhost user interface: {}, vhostUser: {}", swIfName, vhostUser); + throw new VppApiInvocationException("createVhostUserIf", reply.context, reply.retval); + } else { + LOG.debug("Vhost user interface created successfully for: {}, vhostUser: {}", swIfName, vhostUser); + // Add new interface to our interface context + interfaceContext.addName(reply.swIfIndex, swIfName); + } + } + + private CreateVhostUserIf getCreateVhostUserIfRequest(final VhostUser vhostUser) { + CreateVhostUserIf request = new CreateVhostUserIf(); + request.isServer = V3poUtils.booleanToByte(VhostUserRole.Server.equals(vhostUser.getRole())); + request.sockFilename = vhostUser.getSocket().getBytes(); + request.renumber = 0; // TODO + request.customDevInstance = 0; // TODO + request.useCustomMac = 0; + request.macAddress = new byte[]{}; + return request; + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<VhostUser> id, + @Nonnull final VhostUser dataBefore, @Nonnull final VhostUser dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException.UpdateFailedException { + if (dataBefore.equals(dataAfter)) { + LOG.debug("dataBefore equals dataAfter, update will not be performed"); + return; + } + try { + modifyVhostUserIf(id.firstKeyOf(Interface.class).getName(), dataAfter); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + private void modifyVhostUserIf(final String swIfName, final VhostUser vhostUser) throws VppApiInvocationException { + LOG.debug("Updating vhost user interface: name={}, vhostUser={}", swIfName, vhostUser); + final CompletionStage<ModifyVhostUserIfReply> modifyVhostUserIfReplyCompletionStage = + getFutureJVpp() + .modifyVhostUserIf(getModifyVhostUserIfRequest(vhostUser, interfaceContext.getIndex(swIfName))); + + final ModifyVhostUserIfReply reply = + V3poUtils.getReply(modifyVhostUserIfReplyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { + LOG.debug("Failed to update vhost user interface: {}, vhostUser: {}", swIfName, vhostUser); + throw new VppApiInvocationException("modifyVhostUserIf", reply.context, reply.retval); + } else { + LOG.debug("Vhost user interface updated successfully for: {}, vhostUser: {}", swIfName, vhostUser); + } + } + + private ModifyVhostUserIf getModifyVhostUserIfRequest(final VhostUser vhostUser, final int swIfIndex) { + ModifyVhostUserIf request = new ModifyVhostUserIf(); + request.isServer = V3poUtils.booleanToByte(VhostUserRole.Server.equals(vhostUser.getRole())); + request.sockFilename = vhostUser.getSocket().getBytes(); + request.renumber = 0; // TODO + request.customDevInstance = 0; // TODO + request.swIfIndex = swIfIndex; + return request; + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VhostUser> id, + @Nonnull final VhostUser dataBefore, @Nonnull final Context writeContext) + throws WriteFailedException.DeleteFailedException { + try { + deleteVhostUserIf(id.firstKeyOf(Interface.class).getName(), dataBefore); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.DeleteFailedException(id, e); + } + } + + private void deleteVhostUserIf(final String swIfName, final VhostUser vhostUser) throws VppApiInvocationException { + LOG.debug("Deleting vhost user interface: name={}, vhostUser={}", swIfName, vhostUser); + final CompletionStage<DeleteVhostUserIfReply> deleteVhostUserIfReplyCompletionStage = + getFutureJVpp().deleteVhostUserIf(getDeleteVhostUserIfRequest(interfaceContext.getIndex(swIfName))); + + final DeleteVhostUserIfReply reply = + V3poUtils.getReply(deleteVhostUserIfReplyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { + LOG.debug("Failed to delete vhost user interface: {}, vhostUser: {}", swIfName, vhostUser); + throw new VppApiInvocationException("modifyVhostUserIf", reply.context, reply.retval); + } else { + LOG.debug("Vhost user interface deleted successfully for: {}, vhostUser: {}", swIfName, vhostUser); + // Remove interface from our interface context + interfaceContext.removeName(swIfName); + } + } + + private DeleteVhostUserIf getDeleteVhostUserIfRequest(final int swIfIndex) { + DeleteVhostUserIf request = new DeleteVhostUserIf(); + request.swIfIndex = swIfIndex; + return request; + } +} 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 index a4a840e32..b5ef6e010 100644 --- 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 @@ -134,7 +134,7 @@ public class VxlanCustomizer extends FutureJVppCustomizer implements ChildWriter throw new VppApiInvocationException("vxlanAddDelTunnel", reply.context, reply.retval); } else { LOG.debug("Vxlan tunnel deleted successfully for: {}, vxlan: {}", swIfName, vxlan); - // Remove interface to our interface context + // Remove interface from our interface context interfaceContext.removeName(swIfName); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java index 62cac3550..09ea09e47 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java @@ -29,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Gauge64; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; import org.openvpp.jvpp.dto.SwInterfaceDetails; import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; @@ -196,6 +197,10 @@ public final class InterfaceUtils { return VxlanTunnel.class; } + if(interfaceName.startsWith("VirtualEthernet")) { + return VhostUser.class; + } + return EthernetCsmacd.class; } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java index a505436c3..1245f6a53 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java @@ -76,6 +76,8 @@ public class TapCustomizer extends FutureJVppCustomizer @Nonnull final Context ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); + // TODO add logging + @SuppressWarnings("unchecked") Map<Integer, SwInterfaceTapDetails> mappedTaps = (Map<Integer, SwInterfaceTapDetails>) ctx.get(DUMPED_TAPS_CONTEXT_KEY); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java new file mode 100644 index 000000000..4b9c7c8bc --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java @@ -0,0 +1,121 @@ +/* + * 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.interfacesstate; + +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletionStage; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VhostUser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VhostUserBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceVhostUserDetails; +import org.openvpp.jvpp.dto.SwInterfaceVhostUserDetailsReplyDump; +import org.openvpp.jvpp.dto.SwInterfaceVhostUserDump; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class VhostUserCustomizer extends FutureJVppCustomizer + implements ChildReaderCustomizer<VhostUser, VhostUserBuilder> { + + private static final Logger LOG = LoggerFactory.getLogger(VhostUserCustomizer.class); + public static final String DUMPED_VHOST_USERS_CONTEXT_KEY = VhostUserCustomizer.class.getName() + "dumpedVhostUsersDuringGetAllIds"; + private NamingContext interfaceContext; + + public VhostUserCustomizer(@Nonnull final FutureJVpp jvpp, + final NamingContext interfaceContext) { + super(jvpp); + this.interfaceContext = interfaceContext; + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, + @Nonnull VhostUser readValue) { + ((VppInterfaceStateAugmentationBuilder) parentBuilder).setVhostUser(readValue); + } + + @Nonnull + @Override + public VhostUserBuilder getBuilder( + @Nonnull InstanceIdentifier<VhostUser> id) { + return new VhostUserBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<VhostUser> id, + @Nonnull final VhostUserBuilder builder, + @Nonnull final Context ctx) throws ReadFailedException { + final InterfaceKey key = id.firstKeyOf(Interface.class); + + @SuppressWarnings("unchecked") + Map<Integer, SwInterfaceVhostUserDetails> mappedVhostUsers = + (Map<Integer, SwInterfaceVhostUserDetails>) ctx.get(DUMPED_VHOST_USERS_CONTEXT_KEY); + + if(mappedVhostUsers == null) { + // Full VhostUser dump has to be performed here, no filter or anything is here to help so at least we cache it + final SwInterfaceVhostUserDump request = new SwInterfaceVhostUserDump(); + final CompletionStage<SwInterfaceVhostUserDetailsReplyDump> swInterfaceVhostUserDetailsReplyDumpCompletionStage = + getFutureJVpp().swInterfaceVhostUserDump(request); + final SwInterfaceVhostUserDetailsReplyDump reply = + V3poUtils.getReply(swInterfaceVhostUserDetailsReplyDumpCompletionStage.toCompletableFuture()); + + if(null == reply || null == reply.swInterfaceVhostUserDetails) { + mappedVhostUsers = Collections.emptyMap(); + } else { + final List<SwInterfaceVhostUserDetails> swInterfaceVhostUserDetails = reply.swInterfaceVhostUserDetails; + // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes + mappedVhostUsers = swInterfaceVhostUserDetails.stream() + .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails)); + } + + ctx.put(DUMPED_VHOST_USERS_CONTEXT_KEY, mappedVhostUsers); + } + + // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping + final int index = interfaceContext.getIndex(key.getName()); + final SwInterfaceVhostUserDetails swInterfaceVhostUserDetails = mappedVhostUsers.get(index); + if(swInterfaceVhostUserDetails == null) { + // Not a VhostUser interface type + return; + } + + builder.setRole(swInterfaceVhostUserDetails.isServer == 1 ? VhostUserRole.Server : VhostUserRole.Client); + builder.setFeatures(BigInteger.valueOf(swInterfaceVhostUserDetails.features)); + builder.setNumMemoryRegions((long) swInterfaceVhostUserDetails.numRegions); + builder.setSocket(V3poUtils.toString(swInterfaceVhostUserDetails.sockFilename)); + builder.setVirtioNetHdrSize((long) swInterfaceVhostUserDetails.virtioNetHdrSz); + builder.setConnectError(Integer.toString(swInterfaceVhostUserDetails.sockErrno)); + // TODO add logging + } +} 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 index 392dc4666..8742d1d60 100644 --- 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 @@ -24,6 +24,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.BiConsumer; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; import org.openvpp.jvpp.dto.JVppReply; @@ -96,4 +97,13 @@ public final class V3poUtils { private static byte parseHexByte(final String aByte) { return (byte)Integer.parseInt(aByte, 16); } + + /** + * Returns 0 if argument is null or false, 1 otherwise. + * @param value Boolean value to be converted + * @return byte value equal to 0 or 1 + */ + public static byte booleanToByte(@Nullable final Boolean value) { + return value != null && value ? (byte) 1 : (byte) 0; + } } |