2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.bgpmanager;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.stream.Collectors;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.apache.commons.lang3.StringUtils;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
21 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
22 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
23 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
24 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase.EncapType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 public class FibDSWriter {
43 private static final Logger LOG = LoggerFactory.getLogger(FibDSWriter.class);
44 private final DataBroker dataBroker;
45 private final SingleTransactionDataBroker singleTxDB;
46 private final BgpUtil bgpUtil;
49 public FibDSWriter(final DataBroker dataBroker, final BgpUtil bgpUtil) {
50 this.dataBroker = dataBroker;
51 this.bgpUtil = bgpUtil;
52 this.singleTxDB = new SingleTransactionDataBroker(dataBroker);
55 public synchronized void addFibEntryToDS(String rd, String macAddress, String prefix, List<String> nextHopList,
56 VrfEntry.EncapType encapType, int label, long l3vni,
57 String gatewayMacAddress, RouteOrigin origin) {
58 if (rd == null || rd.isEmpty()) {
59 LOG.error("Prefix {} not associated with vpn", prefix);
63 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
64 for (String nextHop : nextHopList) {
65 if (nextHop == null || nextHop.isEmpty()) {
66 LOG.error("nextHop list contains null element");
69 LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
72 // Looking for existing prefix in MDSAL database
73 InstanceIdentifier<VrfEntry> vrfEntryId =
74 InstanceIdentifier.builder(FibEntries.class)
75 .child(VrfTables.class, new VrfTablesKey(rd))
76 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
78 VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
79 buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni, macAddress,
80 gatewayMacAddress, nextHopList);
81 bgpUtil.update(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
84 public void addMacEntryToDS(String rd, String macAddress, String prefix,
85 List<String> nextHopList, VrfEntry.EncapType encapType,
86 long l2vni, String gatewayMacAddress, RouteOrigin origin) {
87 if (StringUtils.isEmpty(rd)) {
88 LOG.error("Mac {} not associated with vpn", macAddress);
92 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
93 for (String nextHop : nextHopList) {
94 if (StringUtils.isEmpty(nextHop)) {
95 LOG.error("nextHop list contains null element for macVrf");
100 MacVrfEntryBuilder macEntryBuilder = new MacVrfEntryBuilder().setOrigin(origin.getValue());
101 buildVpnEncapSpecificInfo(macEntryBuilder, encapType, l2vni, macAddress,
102 gatewayMacAddress, nextHopList);
103 macEntryBuilder.setMac(macAddress);
104 macEntryBuilder.setDestPrefix(prefix);
105 InstanceIdentifier<MacVrfEntry> macEntryId =
106 InstanceIdentifier.builder(FibEntries.class)
107 .child(VrfTables.class, new VrfTablesKey(rd))
108 .child(MacVrfEntry.class, new MacVrfEntryKey(macAddress)).build();
109 bgpUtil.update(LogicalDatastoreType.CONFIGURATION, macEntryId, macEntryBuilder.build());
112 private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder,
113 VrfEntry.EncapType encapType, long label, long l3vni, String macAddress,
114 String gatewayMac, List<String> nextHopList) {
115 if (!encapType.equals(VrfEntry.EncapType.Mplsgre)) {
116 builder.setL3vni(l3vni);
118 builder.setEncapType(encapType);
119 builder.setGatewayMacAddress(gatewayMac);
120 Long lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
121 List<RoutePaths> routePaths = nextHopList.stream()
122 .filter(StringUtils::isNotEmpty)
123 .map(nextHop -> FibHelper.buildRoutePath(nextHop, lbl)).collect(Collectors.toList());
124 builder.setRoutePaths(routePaths);
127 private static void buildVpnEncapSpecificInfo(MacVrfEntryBuilder builder,
128 VrfEntry.EncapType encapType, long l2vni, String macAddress,
129 String gatewayMac, List<String> nextHopList) {
130 builder.setEncapType(encapType);
131 builder.setGatewayMacAddress(gatewayMac);
132 builder.setL2vni(l2vni);
133 List<RoutePaths> routePaths = nextHopList.stream()
134 .filter(StringUtils::isNotEmpty)
135 .map(nextHop -> FibHelper.buildRoutePath(nextHop, null)).collect(Collectors.toList());
136 builder.setRoutePaths(routePaths);
139 public synchronized void removeFibEntryFromDS(String rd, String prefix) {
141 if (rd == null || rd.isEmpty()) {
142 LOG.error("Prefix {} not associated with vpn", prefix);
145 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
147 InstanceIdentifierBuilder<VrfEntry> idBuilder =
148 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
149 VrfEntry.class, new VrfEntryKey(prefix));
150 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
151 bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
155 public void removeMacEntryFromDS(String rd, String macAddress) {
157 if (StringUtils.isEmpty(rd)) {
158 LOG.error("Mac {} not associated with vpn", macAddress);
161 LOG.debug("Removing Mac fib entry with Mac {} from vrf table for rd {}", macAddress, rd);
163 InstanceIdentifierBuilder<MacVrfEntry> idBuilder =
164 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
165 MacVrfEntry.class, new MacVrfEntryKey(macAddress));
166 InstanceIdentifier<MacVrfEntry> macEntryId = idBuilder.build();
167 bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, macEntryId);
171 public synchronized void removeOrUpdateFibEntryFromDS(String rd, String prefix, String nextHop) {
173 if (rd == null || rd.isEmpty()) {
174 LOG.error("Prefix {} not associated with vpn", prefix);
177 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} and nextHop {}",
178 prefix, rd, nextHop);
180 InstanceIdentifier<VrfEntry> vrfEntryId =
181 InstanceIdentifier.builder(FibEntries.class)
182 .child(VrfTables.class, new VrfTablesKey(rd))
183 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
184 Optional<VrfEntry> existingVrfEntry =
185 singleTxDB.syncReadOptional(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
186 List<RoutePaths> routePaths =
187 existingVrfEntry.toJavaUtil().map(VrfEntry::getRoutePaths).orElse(Collections.emptyList());
188 if (routePaths.size() == 1) {
189 if (routePaths.get(0).getNexthopAddress().equals(nextHop)) {
190 bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
194 .map(RoutePaths::getNexthopAddress)
195 .filter(nextHopAddress -> nextHopAddress.equals(nextHop))
198 InstanceIdentifier<RoutePaths> routePathId =
199 FibHelper.buildRoutePathId(rd, prefix, nextHop);
200 bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, routePathId);
203 } catch (ReadFailedException e) {
204 LOG.error("Error while reading vrfEntry for rd {}, prefix {}", rd, prefix);
210 public synchronized void removeVrfSubFamilyFromDS(String rd, AddressFamily addressFamily) {
215 LOG.debug("removeVrfSubFamilyFromDS : addressFamily {} from vrf rd {}",
218 InstanceIdentifier<VrfTables> id = InstanceIdentifier.create(FibEntries.class)
219 .child(VrfTables.class, new VrfTablesKey(rd));
221 VrfTables vrfTable = singleTxDB.syncRead(LogicalDatastoreType.CONFIGURATION, id);
222 if (vrfTable != null) {
223 List<VrfEntry> vrfEntries = vrfTable.getVrfEntry();
224 if (vrfEntries == null) {
225 String errMsg = "removeVrfSubFamilyFromDS : VrfEntry not found for rd " + rd;
229 for (VrfEntry vrfEntry : vrfEntries) {
230 boolean found = false;
231 if (vrfEntry.getEncapType() != null) {
232 if (!vrfEntry.getEncapType().equals(EncapType.Mplsgre)
233 && addressFamily == AddressFamily.L2VPN) {
235 } else if (vrfEntry.getEncapType().equals(EncapType.Mplsgre)) {
236 if (addressFamily == AddressFamily.IPV4
237 && FibHelper.isIpv4Prefix(vrfEntry.getDestPrefix())) {
239 } else if (addressFamily == AddressFamily.IPV6
240 && FibHelper.isIpv6Prefix(vrfEntry.getDestPrefix())) {
245 if (found == false) {
248 bgpUtil.removeVrfEntry(rd, vrfEntry);
251 } catch (ReadFailedException rfe) {
252 String errMsg = "removeVrfSubFamilyFromDS : Internal Error rd " + rd;
253 LOG.error(errMsg, rfe);
258 public synchronized void removeVrfFromDS(String rd) {
259 LOG.debug("Removing vrf table for rd {}", rd);
261 InstanceIdentifierBuilder<VrfTables> idBuilder =
262 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
263 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
265 bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, vrfTableId);