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;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.stream.Collectors;
16 import org.apache.commons.lang3.StringUtils;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
20 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
21 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
22 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 public class FibDSWriter {
39 private static final Logger LOG = LoggerFactory.getLogger(FibDSWriter.class);
40 private final DataBroker dataBroker;
41 private final SingleTransactionDataBroker singleTxDB;
43 public FibDSWriter(final DataBroker dataBroker) {
44 this.dataBroker = dataBroker;
45 this.singleTxDB = new SingleTransactionDataBroker(dataBroker);
48 public synchronized void addFibEntryToDS(String rd, String macAddress, String prefix, List<String> nextHopList,
49 VrfEntry.EncapType encapType, int label, long l3vni,
50 String gatewayMacAddress, RouteOrigin origin) {
51 if (rd == null || rd.isEmpty()) {
52 LOG.error("Prefix {} not associated with vpn", prefix);
56 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
57 for (String nextHop : nextHopList) {
58 if (nextHop == null || nextHop.isEmpty()) {
59 LOG.error("nextHop list contains null element");
62 LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
65 // Looking for existing prefix in MDSAL database
66 InstanceIdentifier<VrfEntry> vrfEntryId =
67 InstanceIdentifier.builder(FibEntries.class)
68 .child(VrfTables.class, new VrfTablesKey(rd))
69 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
71 VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
72 buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, (long)label, l3vni, macAddress,
73 gatewayMacAddress, nextHopList);
74 BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
77 public void addMacEntryToDS(String rd, String macAddress, String prefix,
78 List<String> nextHopList, VrfEntry.EncapType encapType,
79 long l2vni, String gatewayMacAddress, RouteOrigin origin) {
80 if (StringUtils.isEmpty(rd)) {
81 LOG.error("Mac {} not associated with vpn", macAddress);
85 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
86 for (String nextHop : nextHopList) {
87 if (StringUtils.isEmpty(nextHop)) {
88 LOG.error("nextHop list contains null element for macVrf");
93 MacVrfEntryBuilder macEntryBuilder = new MacVrfEntryBuilder().setOrigin(origin.getValue());
94 buildVpnEncapSpecificInfo(macEntryBuilder, encapType, l2vni, macAddress,
95 gatewayMacAddress, nextHopList);
96 macEntryBuilder.setMac(macAddress);
97 macEntryBuilder.setDestPrefix(prefix);
98 InstanceIdentifier<MacVrfEntry> macEntryId =
99 InstanceIdentifier.builder(FibEntries.class)
100 .child(VrfTables.class, new VrfTablesKey(rd))
101 .child(MacVrfEntry.class, new MacVrfEntryKey(macAddress)).build();
102 BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, macEntryId, macEntryBuilder.build());
105 private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder,
106 VrfEntry.EncapType encapType, long label, long l3vni, String macAddress,
107 String gatewayMac, List<String> nextHopList) {
108 if (!encapType.equals(VrfEntry.EncapType.Mplsgre)) {
109 builder.setL3vni(l3vni);
111 builder.setEncapType(encapType);
112 builder.setGatewayMacAddress(gatewayMac);
113 Long lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
114 List<RoutePaths> routePaths = nextHopList.stream()
115 .filter(StringUtils::isNotEmpty)
116 .map(nextHop -> FibHelper.buildRoutePath(nextHop, lbl)).collect(Collectors.toList());
117 builder.setRoutePaths(routePaths);
120 private static void buildVpnEncapSpecificInfo(MacVrfEntryBuilder builder,
121 VrfEntry.EncapType encapType, long l2vni, String macAddress,
122 String gatewayMac, List<String> nextHopList) {
123 builder.setEncapType(encapType);
124 builder.setGatewayMacAddress(gatewayMac);
125 builder.setL2vni(l2vni);
126 List<RoutePaths> routePaths = nextHopList.stream()
127 .filter(StringUtils::isNotEmpty)
128 .map(nextHop -> FibHelper.buildRoutePath(nextHop, null)).collect(Collectors.toList());
129 builder.setRoutePaths(routePaths);
132 public synchronized void removeFibEntryFromDS(String rd, String prefix) {
134 if (rd == null || rd.isEmpty()) {
135 LOG.error("Prefix {} not associated with vpn", prefix);
138 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
140 InstanceIdentifierBuilder<VrfEntry> idBuilder =
141 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
142 VrfEntry.class, new VrfEntryKey(prefix));
143 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
144 BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
148 public void removeMacEntryFromDS(String rd, String macAddress) {
150 if (StringUtils.isEmpty(rd)) {
151 LOG.error("Mac {} not associated with vpn", macAddress);
154 LOG.debug("Removing Mac fib entry with Mac {} from vrf table for rd {}", macAddress, rd);
156 InstanceIdentifierBuilder<MacVrfEntry> idBuilder =
157 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
158 MacVrfEntry.class, new MacVrfEntryKey(macAddress));
159 InstanceIdentifier<MacVrfEntry> macEntryId = idBuilder.build();
160 BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, macEntryId);
164 public synchronized void removeOrUpdateFibEntryFromDS(String rd, String prefix, String nextHop) {
166 if (rd == null || rd.isEmpty()) {
167 LOG.error("Prefix {} not associated with vpn", prefix);
170 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} and nextHop {}",
171 prefix, rd, nextHop);
173 InstanceIdentifier<VrfEntry> vrfEntryId =
174 InstanceIdentifier.builder(FibEntries.class)
175 .child(VrfTables.class, new VrfTablesKey(rd))
176 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
177 Optional<VrfEntry> existingVrfEntry =
178 singleTxDB.syncReadOptional(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
179 List<RoutePaths> routePaths =
180 existingVrfEntry.transform(VrfEntry::getRoutePaths).or(Collections.EMPTY_LIST);
181 if (routePaths.size() == 1) {
182 if (routePaths.get(0).getNexthopAddress().equals(nextHop)) {
183 BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
187 .map(RoutePaths::getNexthopAddress)
188 .filter(nextHopAddress -> nextHopAddress.equals(nextHop))
191 InstanceIdentifier<RoutePaths> routePathId =
192 FibHelper.buildRoutePathId(rd, prefix, nextHop);
193 BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION,
197 } catch (ReadFailedException e) {
198 LOG.error("Error while reading vrfEntry for rd {}, prefix {}", rd, prefix);
203 public synchronized void removeVrfFromDS(String rd) {
204 LOG.debug("Removing vrf table for rd {}", rd);
206 InstanceIdentifierBuilder<VrfTables> idBuilder =
207 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
208 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
210 BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId);