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.Preconditions;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
16 import java.util.stream.Collectors;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.apache.commons.lang3.StringUtils;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
24 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
25 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
26 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase.EncapType;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
40 import org.opendaylight.yangtools.yang.common.Uint32;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 public class FibDSWriter {
46 private static final Logger LOG = LoggerFactory.getLogger(FibDSWriter.class);
47 private final SingleTransactionDataBroker singleTxDB;
48 private final BgpUtil bgpUtil;
49 private final Map<String, ArrayList<String>> fibMap = new HashMap<>();
52 public FibDSWriter(final DataBroker dataBroker, final BgpUtil bgpUtil) {
53 this.bgpUtil = bgpUtil;
54 this.singleTxDB = new SingleTransactionDataBroker(dataBroker);
57 public synchronized void clearFibMap() {
61 public synchronized void addEntryToFibMap(String rd, String prefix, String nextHop) {
62 ArrayList<String> temp = new ArrayList<String>();
63 if ((fibMap.get(appendrdtoprefix(rd, prefix)) != null)) {
64 temp.addAll(fibMap.get(appendrdtoprefix(rd, prefix)));
67 fibMap.put(appendrdtoprefix(rd, prefix),temp);
68 LOG.debug("addEntryToFibMap rd {} prefix {} nexthop {}",
73 public synchronized void addFibEntryToDS(String rd, String prefix, List<String> nextHopList,
74 VrfEntry.EncapType encapType, Uint32 label, Uint32 l3vni,
75 String gatewayMacAddress, RouteOrigin origin) {
76 if (rd == null || rd.isEmpty()) {
77 LOG.error("Prefix {} not associated with vpn", prefix);
81 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
82 for (String nextHop : nextHopList) {
83 if (nextHop == null || nextHop.isEmpty()) {
84 LOG.error("nextHop list contains null element");
87 LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
90 LOG.debug("addFibEntryToDS rd {} prefix {} NH {}",
91 rd, prefix, nextHopList.get(0));
93 ArrayList<String> temp = new ArrayList<String>();
94 if ((fibMap.get(appendrdtoprefix(rd, prefix)) != null)) {
95 temp.addAll(fibMap.get(appendrdtoprefix(rd, prefix)));
97 if (!temp.contains(nextHopList.get(0))) {
98 temp.addAll(nextHopList);
99 fibMap.put(appendrdtoprefix(rd, prefix), temp);
102 // Looking for existing prefix in MDSAL database
103 InstanceIdentifier<VrfEntry> vrfEntryId =
104 InstanceIdentifier.builder(FibEntries.class)
105 .child(VrfTables.class, new VrfTablesKey(rd))
106 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
108 VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
109 buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni,
110 gatewayMacAddress, nextHopList);
111 bgpUtil.update(vrfEntryId, vrfEntryBuilder.build());
114 private String appendrdtoprefix(String rd, String prefix) {
115 return rd + "/" + prefix;
118 public void addMacEntryToDS(String rd, String macAddress, String prefix,
119 List<String> nextHopList, VrfEntry.EncapType encapType,
120 Uint32 l2vni, String gatewayMacAddress, RouteOrigin origin) {
121 if (StringUtils.isEmpty(rd)) {
122 LOG.error("Mac {} not associated with vpn", macAddress);
126 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
127 for (String nextHop : nextHopList) {
128 if (StringUtils.isEmpty(nextHop)) {
129 LOG.error("nextHop list contains null element for macVrf");
134 MacVrfEntryBuilder macEntryBuilder = new MacVrfEntryBuilder().setOrigin(origin.getValue());
135 buildVpnEncapSpecificInfo(macEntryBuilder, encapType, l2vni,
136 gatewayMacAddress, nextHopList);
137 macEntryBuilder.setMac(macAddress);
138 macEntryBuilder.setDestPrefix(prefix);
139 InstanceIdentifier<MacVrfEntry> macEntryId =
140 InstanceIdentifier.builder(FibEntries.class)
141 .child(VrfTables.class, new VrfTablesKey(rd))
142 .child(MacVrfEntry.class, new MacVrfEntryKey(macAddress)).build();
143 bgpUtil.update(macEntryId, macEntryBuilder.build());
146 private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder,
147 VrfEntry.EncapType encapType, Uint32 label, Uint32 l3vni,
148 String gatewayMac, List<String> nextHopList) {
149 if (!encapType.equals(VrfEntry.EncapType.Mplsgre)) {
150 builder.setL3vni(l3vni);
152 builder.setEncapType(encapType);
153 builder.setGatewayMacAddress(gatewayMac);
154 Uint32 lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
155 List<RoutePaths> routePaths = nextHopList.stream()
156 .filter(StringUtils::isNotEmpty)
157 .map(nextHop -> FibHelper.buildRoutePath(nextHop, lbl)).collect(Collectors.toList());
158 builder.setRoutePaths(routePaths);
161 private static void buildVpnEncapSpecificInfo(MacVrfEntryBuilder builder,
162 VrfEntry.EncapType encapType, Uint32 l2vni,
163 String gatewayMac, List<String> nextHopList) {
164 builder.setEncapType(encapType);
165 builder.setGatewayMacAddress(gatewayMac);
166 builder.setL2vni(l2vni);
167 List<RoutePaths> routePaths = nextHopList.stream()
168 .filter(StringUtils::isNotEmpty)
169 .map(nextHop -> FibHelper.buildRoutePath(nextHop, null)).collect(Collectors.toList());
170 builder.setRoutePaths(routePaths);
173 public synchronized void removeFibEntryFromDS(String rd, String prefix) {
175 if (rd == null || rd.isEmpty()) {
176 LOG.error("Prefix {} not associated with vpn", prefix);
179 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
181 InstanceIdentifierBuilder<VrfEntry> idBuilder =
182 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
183 VrfEntry.class, new VrfEntryKey(prefix));
184 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
185 bgpUtil.delete(vrfEntryId);
189 public void removeMacEntryFromDS(String rd, String macAddress) {
191 if (StringUtils.isEmpty(rd)) {
192 LOG.error("Mac {} not associated with vpn", macAddress);
195 LOG.debug("Removing Mac fib entry with Mac {} from vrf table for rd {}", macAddress, rd);
197 InstanceIdentifierBuilder<MacVrfEntry> idBuilder =
198 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
199 MacVrfEntry.class, new MacVrfEntryKey(macAddress));
200 InstanceIdentifier<MacVrfEntry> macEntryId = idBuilder.build();
201 bgpUtil.delete(macEntryId);
205 public synchronized void removeOrUpdateFibEntryFromDS(String rd, String prefix, String nextHop) {
207 if (rd == null || rd.isEmpty()) {
208 LOG.error("Prefix {} not associated with vpn", prefix);
211 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} and nextHop {}",
212 prefix, rd, nextHop);
215 InstanceIdentifier<VrfEntry> vrfEntryId =
216 InstanceIdentifier.builder(FibEntries.class)
217 .child(VrfTables.class, new VrfTablesKey(rd))
218 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
220 LOG.debug("removeOrUpdateFibEntryFromDS rd {} prefix {} NH {}",
221 rd, prefix, nextHop);
223 if (fibMap.get(appendrdtoprefix(rd,prefix)) != null) { //Key is there
224 // If nexthop is there, delete it from List
225 List<String> list = fibMap.get(appendrdtoprefix(rd,prefix));
226 list.remove(nextHop);
227 if (list.isEmpty()) {
228 fibMap.remove(appendrdtoprefix(rd, prefix));
229 bgpUtil.delete(vrfEntryId);
231 InstanceIdentifier<RoutePaths> routePathId =
232 FibHelper.buildRoutePathId(rd, prefix, nextHop);
233 bgpUtil.delete(routePathId);
236 LOG.error("Invalid Delete from Quagga, RD {} Prefix {} Nexthop {} ",
242 public synchronized void removeVrfSubFamilyFromDS(String rd, AddressFamily addressFamily) {
247 LOG.debug("removeVrfSubFamilyFromDS : addressFamily {} from vrf rd {}",
250 InstanceIdentifier<VrfTables> id = InstanceIdentifier.create(FibEntries.class)
251 .child(VrfTables.class, new VrfTablesKey(rd));
253 VrfTables vrfTable = singleTxDB.syncRead(LogicalDatastoreType.CONFIGURATION, id);
254 if (vrfTable != null) {
255 List<VrfEntry> vrfEntries = vrfTable.getVrfEntry();
256 if (vrfEntries == null) {
257 LOG.error("removeVrfSubFamilyFromDS : VrfEntry not found for rd {}", rd);
260 for (VrfEntry vrfEntry : vrfEntries) {
261 boolean found = false;
262 if (vrfEntry.getEncapType() != null) {
263 if (!vrfEntry.getEncapType().equals(EncapType.Mplsgre)
264 && addressFamily == AddressFamily.L2VPN) {
266 } else if (vrfEntry.getEncapType().equals(EncapType.Mplsgre)) {
267 if (addressFamily == AddressFamily.IPV4
268 && FibHelper.isIpv4Prefix(vrfEntry.getDestPrefix())) {
270 } else if (addressFamily == AddressFamily.IPV6
271 && FibHelper.isIpv6Prefix(vrfEntry.getDestPrefix())) {
276 if (found == false) {
279 bgpUtil.removeVrfEntry(rd, vrfEntry);
282 } catch (ReadFailedException rfe) {
283 LOG.error("removeVrfSubFamilyFromDS : Internal Error rd {}", rd, rfe);
288 public synchronized void removeVrfFromDS(String rd) {
289 LOG.debug("Removing vrf table for rd {}", rd);
291 InstanceIdentifierBuilder<VrfTables> idBuilder =
292 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
293 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
295 bgpUtil.delete(vrfTableId);