2 * Copyright (c) 2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package io.fd.honeycomb.v3po.translate.v3po.interfacesstate;
19 import static com.google.common.base.Preconditions.checkState;
21 import com.google.common.base.Preconditions;
22 import io.fd.honeycomb.v3po.translate.read.ReadContext;
23 import io.fd.honeycomb.v3po.translate.read.ReadFailedException;
24 import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer;
25 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
26 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
27 import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils;
28 import java.util.Optional;
29 import java.util.concurrent.CompletableFuture;
30 import javax.annotation.Nonnull;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2Builder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.interconnection.BridgeBasedBuilder;
37 import org.opendaylight.yangtools.concepts.Builder;
38 import org.opendaylight.yangtools.yang.binding.DataObject;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.openvpp.jvpp.dto.BridgeDomainDetails;
41 import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump;
42 import org.openvpp.jvpp.dto.BridgeDomainDump;
43 import org.openvpp.jvpp.dto.BridgeDomainSwIfDetails;
44 import org.openvpp.jvpp.dto.SwInterfaceDetails;
45 import org.openvpp.jvpp.future.FutureJVpp;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
50 * Customizer for reading ietf-interfaces:interfaces-state/interface/iface_name/v3po:l2
52 public class L2Customizer extends FutureJVppCustomizer
53 implements ChildReaderCustomizer<L2, L2Builder> {
55 private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class);
56 private final NamingContext interfaceContext;
57 private final NamingContext bridgeDomainContext;
59 public L2Customizer(@Nonnull final FutureJVpp futureJvpp,
60 @Nonnull final NamingContext interfaceContext,
61 @Nonnull final NamingContext bridgeDomainContext) {
63 this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
64 this.bridgeDomainContext = Preconditions.checkNotNull(bridgeDomainContext, "bridgeDomainContext should not be null");
68 public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final L2 readValue) {
69 ((VppInterfaceStateAugmentationBuilder) parentBuilder).setL2(readValue);
74 public L2Builder getBuilder(@Nonnull final InstanceIdentifier<L2> id) {
75 return new L2Builder();
79 public void readCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2Builder builder,
80 @Nonnull final ReadContext ctx) throws ReadFailedException {
81 LOG.debug("Reading attributes for L2: {}", id);
82 final InterfaceKey key = id.firstKeyOf(Interface.class);
83 final int ifaceId = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
85 final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key,
86 ifaceId, ctx.getModificationCache());
87 LOG.debug("Interface details for interface: {}, details: {}", key.getName(), iface);
89 final BridgeDomainDetailsReplyDump dumpReply = getDumpReply();
90 final Optional<BridgeDomainSwIfDetails> bdForInterface = getBridgeDomainForInterface(ifaceId, dumpReply);
91 if (bdForInterface.isPresent()) {
92 final BridgeDomainSwIfDetails bdSwIfDetails = bdForInterface.get();
93 final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder();
94 bbBuilder.setBridgeDomain(bridgeDomainContext.getName(bdSwIfDetails.bdId, ctx.getMappingContext()));
96 // Set BVI if the bridgeDomainDetails.bviSwIfIndex == current sw if index
97 final Optional<BridgeDomainDetails> bridgeDomainForInterface =
98 getBridgeDomainForInterface(ifaceId, dumpReply, bdForInterface.get().bdId);
99 // Since we already found an interface assigned to a bridge domain, the details for BD must be present
100 checkState(bridgeDomainForInterface.isPresent());
101 if(bridgeDomainForInterface.get().bviSwIfIndex == ifaceId) {
102 bbBuilder.setBridgedVirtualInterface(true);
105 if (bdSwIfDetails.shg != 0) {
106 bbBuilder.setSplitHorizonGroup((short)bdSwIfDetails.shg);
108 builder.setInterconnection(bbBuilder.build());
111 // TODO is there a way to check if interconnection is XconnectBased?
114 private Optional<BridgeDomainSwIfDetails> getBridgeDomainForInterface(final int ifaceId,
115 final BridgeDomainDetailsReplyDump reply) {
116 if (null == reply || null == reply.bridgeDomainSwIfDetails || reply.bridgeDomainSwIfDetails.isEmpty()) {
117 return Optional.empty();
119 // interface can be added to only one BD only
120 return reply.bridgeDomainSwIfDetails.stream().filter(a -> a.swIfIndex == ifaceId).findFirst();
124 private Optional<BridgeDomainDetails> getBridgeDomainForInterface(final int ifaceId,
125 final BridgeDomainDetailsReplyDump reply,
127 return reply.bridgeDomainDetails.stream().filter(a -> a.bdId == bdId).findFirst();
130 private BridgeDomainDetailsReplyDump getDumpReply() {
131 // We need to perform full bd dump, because there is no way
132 // to ask VPP for BD details given interface id/name (TODO add it to vpp.api?)
133 // TODO cache dump result
134 final BridgeDomainDump request = new BridgeDomainDump();
137 final CompletableFuture<BridgeDomainDetailsReplyDump> bdCompletableFuture =
138 getFutureJVpp().bridgeDomainSwIfDump(request).toCompletableFuture();
139 return V3poUtils.getReply(bdCompletableFuture);