/* * 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.hc2vpp.v3po.read; import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.v3po.DisabledInterfacesManager; import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.MappingContext; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; import io.fd.jvpp.core.dto.SwInterfaceDetails; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfacesBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface.AdminStatus; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface.OperStatus; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Customizer for reading ietf-interfaces:interfaces/interface. */ public class InterfaceCustomizer implements InitializingListReaderCustomizer, ByteDataTranslator, InterfaceDataTranslator { private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class); private final NamingContext interfaceNamingContext; private final DisabledInterfacesManager interfaceDisableContext; private final InterfaceCacheDumpManager dumpManager; public InterfaceCustomizer(@Nonnull final NamingContext interfaceNamingContext, @Nonnull final DisabledInterfacesManager interfaceDisableContext, @Nonnull final InterfaceCacheDumpManager dumpManager) { this.interfaceNamingContext = interfaceNamingContext; this.interfaceDisableContext = interfaceDisableContext; this.dumpManager = dumpManager; } @Nonnull @Override public InterfaceBuilder getBuilder(@Nonnull InstanceIdentifier id) { return new InterfaceBuilder(); } @Override public void readCurrentAttributes(@Nonnull InstanceIdentifier id, @Nonnull InterfaceBuilder builder, @Nonnull ReadContext ctx) throws ReadFailedException { LOG.debug("Reading attributes for interface: {}", id); final String ifaceName = id.firstKeyOf(id.getTargetType()).getName(); final int index = interfaceNamingContext.getIndex(ifaceName, ctx.getMappingContext()); // Ignore disabled interface (such as deleted VXLAN tunnels) if (interfaceDisableContext.isInterfaceDisabled(index, ctx.getMappingContext())) { LOG.debug("Skipping disabled interface: {}", id); return; } final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, ifaceName); LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface); if (!isRegularInterface(iface)) { LOG.debug("Interface: {} is a sub-interface. Ignoring read request.", ifaceName); return; } builder.setName(ifaceName); builder.setType(getInterfaceType(new String(iface.interfaceName).intern())); builder.setIfIndex(vppIfIndexToYang(iface.swIfIndex)); builder.setAdminStatus(1 == iface.adminUpDown ? AdminStatus.Up : AdminStatus.Down); builder.setOperStatus(1 == iface.linkUpDown ? OperStatus.Up : OperStatus.Down); if (0 != iface.linkSpeed) { builder.setSpeed(vppInterfaceSpeedToYang(iface.linkSpeed)); } if (iface.l2AddressLength == 6) { builder.setPhysAddress(new PhysAddress(vppPhysAddrToYang(iface.l2Address))); } LOG.trace("Base attributes read for interface: {} as: {}", ifaceName, builder); } @Nonnull @Override public List getAllIds(@Nonnull final InstanceIdentifier id, @Nonnull final ReadContext context) throws ReadFailedException { final List interfacesKeys; LOG.trace("Dumping all interfaces to get all IDs"); final MappingContext mappingCtx = context.getMappingContext(); final Set interfacesIdxs = dumpManager.getInterfaces(id, context) .filter(elt -> elt != null) // Filter out disabled interfaces, dont read them // This also prevents child readers in being invoked such as vxlan (which relies on disabling interfaces) .filter(elt -> !interfaceDisableContext .isInterfaceDisabled(elt.swIfIndex, mappingCtx)) // filter out sub-interfaces .filter(InterfaceDataTranslator.INSTANCE::isRegularInterface) .map(elt -> elt.swIfIndex) .collect(Collectors.toSet()); // Clean disabled interfaces list interfaceDisableContext.getDisabledInterfaces(mappingCtx).stream() // Find indices not currently in VPP .filter(interfacesIdxs::contains) // Remove from disabled list ... not disabled if not existing .forEach(idx -> interfaceDisableContext.removeDisabledInterface(idx, mappingCtx)); // Transform indices to keys interfacesKeys = interfacesIdxs.stream() .map(index -> new InterfaceKey(interfaceNamingContext.getName(index, context.getMappingContext()))) .collect(Collectors.toList()); LOG.debug("Interfaces found in VPP: {}", interfacesKeys); return interfacesKeys; } @Override public void merge(@Nonnull final org.opendaylight.yangtools.concepts.Builder builder, @Nonnull final List readData) { ((InterfacesBuilder) builder).setInterface(readData); } @Override public Initialized init( @Nonnull final InstanceIdentifier id, @Nonnull final Interface readValue, @Nonnull final ReadContext ctx) { return Initialized.create(getCfgId(id), new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder() .setName(readValue.getName()) .setType(readValue.getType()) .setEnabled(AdminStatus.Up.equals(readValue.getAdminStatus())) // Not present in interfaces // .setLinkUpDownTrapEnable() .build()); } public static InstanceIdentifier getCfgId( final InstanceIdentifier id) { return InstanceIdentifier.create(Interfaces.class).child( org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey( id.firstKeyOf(Interface.class).getName())); } }