Line data Source code
1 : /*
2 : * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3 : */
4 : #include "bgp/bgp_xmpp_rtarget_manager.h"
5 :
6 : #include <utility>
7 : #include <vector>
8 :
9 : #include <boost/foreach.hpp>
10 :
11 : #include "bgp/ipeer.h"
12 : #include "bgp/bgp_peer_types.h"
13 : #include "bgp/bgp_server.h"
14 : #include "bgp/bgp_xmpp_channel.h"
15 : #include "routing-instance/routing_instance.h"
16 :
17 : using std::make_pair;
18 : using std::pair;
19 : using std::string;
20 : using std::vector;
21 :
22 10062 : BgpXmppRTargetManager::BgpXmppRTargetManager(BgpXmppChannel *bgp_xmpp_channel) :
23 10062 : bgp_xmpp_channel_(bgp_xmpp_channel) {
24 10062 : }
25 :
26 20106 : BgpXmppRTargetManager::~BgpXmppRTargetManager() {
27 20106 : }
28 :
29 15936 : bool BgpXmppRTargetManager::IsSubscriptionEmpty() const {
30 15936 : return bgp_xmpp_channel_->IsSubscriptionEmpty();
31 : }
32 :
33 7333 : bool BgpXmppRTargetManager::IsSubscriptionGrStale(
34 : RoutingInstance *instance) const {
35 7333 : return bgp_xmpp_channel_->IsSubscriptionGrStale(instance);
36 : }
37 :
38 7333 : bool BgpXmppRTargetManager::IsSubscriptionLlgrStale(
39 : RoutingInstance *instance) const {
40 7333 : return bgp_xmpp_channel_->IsSubscriptionLlgrStale(instance);
41 : }
42 :
43 41827 : bool BgpXmppRTargetManager::delete_in_progress() const {
44 41827 : return bgp_xmpp_channel_->delete_in_progress();
45 : }
46 :
47 78141 : const IPeer *BgpXmppRTargetManager::Peer() const {
48 78141 : return bgp_xmpp_channel_->Peer();
49 : }
50 :
51 78141 : void BgpXmppRTargetManager::Enqueue(DBRequest *req) const {
52 : RoutingInstanceMgr *instance_mgr =
53 78141 : bgp_xmpp_channel_->bgp_server()->routing_instance_mgr();
54 78141 : RoutingInstance *master = instance_mgr->GetDefaultRoutingInstance();
55 78140 : BgpTable *table = master->GetTable(Address::RTARGET);
56 78139 : assert(table);
57 78139 : table->Enqueue(req);
58 78141 : }
59 :
60 60367 : BgpAttrPtr BgpXmppRTargetManager::GetRouteTargetRouteAttr() const {
61 60367 : BgpAttrSpec attrs;
62 60367 : BgpAttrNextHop nexthop(bgp_xmpp_channel_->bgp_server()->bgp_identifier());
63 60367 : attrs.push_back(&nexthop);
64 60367 : BgpAttrOrigin origin(BgpAttrOrigin::IGP);
65 60367 : attrs.push_back(&origin);
66 120734 : return bgp_xmpp_channel_->bgp_server()->attr_db()->Locate(attrs);
67 60367 : }
68 :
69 73869 : int BgpXmppRTargetManager::local_autonomous_system() const {
70 73869 : return bgp_xmpp_channel_->bgp_server()->local_autonomous_system();
71 : }
72 :
73 : const BgpXmppRTargetManager::RouteTargetList &
74 14877 : BgpXmppRTargetManager::GetSubscribedRTargets(RoutingInstance *instance) const {
75 14877 : return bgp_xmpp_channel_->GetSubscribedRTargets(instance);
76 : }
77 :
78 37658 : uint32_t BgpXmppRTargetManager::GetRTargetRouteFlag(
79 : const RouteTarget &rtarget) const {
80 : PublishedRTargetRoutes::const_iterator rt_loc =
81 37658 : rtarget_routes_.find(rtarget);
82 37658 : if (rt_loc == rtarget_routes_.end() || rt_loc->second.empty())
83 31019 : return 0;
84 :
85 : // Route is [llgr-]stale only if it is stale for all instances in the set.
86 6639 : uint32_t flags = BgpPath::Stale | BgpPath::LlgrStale;
87 14802 : BOOST_FOREACH(RoutingInstance *routing_instance, rt_loc->second) {
88 7393 : if (!IsSubscriptionGrStale(routing_instance))
89 6623 : flags &= ~BgpPath::Stale;
90 7393 : if (!IsSubscriptionLlgrStale(routing_instance))
91 7373 : flags &= ~BgpPath::LlgrStale;
92 7393 : if (!flags)
93 6623 : break;
94 : }
95 :
96 6639 : return flags;
97 : }
98 :
99 78248 : void BgpXmppRTargetManager::RTargetRouteOp(as_t asn,
100 : const RouteTarget &rtarget,
101 : BgpAttrPtr attr, bool add_change,
102 : uint32_t flags) const {
103 78248 : if (add_change && delete_in_progress())
104 0 : return;
105 :
106 78248 : DBRequest req;
107 78249 : RTargetPrefix rt_prefix(asn, rtarget);
108 78249 : req.key.reset(new RTargetTable::RequestKey(rt_prefix, Peer()));
109 78249 : if (add_change) {
110 : // Find correct rtarget route flags if not already known.
111 41899 : if (!flags)
112 37658 : flags = GetRTargetRouteFlag(rtarget);
113 41899 : req.data.reset(new RTargetTable::RequestData(attr, flags, 0, 0, 0));
114 41899 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
115 : } else {
116 36350 : req.oper = DBRequest::DB_ENTRY_DELETE;
117 : }
118 78249 : Enqueue(&req);
119 78249 : }
120 :
121 1077 : void BgpXmppRTargetManager::ASNUpdateCallback(as_t old_asn,
122 : as_t old_local_asn) const {
123 1077 : if (local_autonomous_system() == (int)old_local_asn)
124 517 : return;
125 1077 : if (IsSubscriptionEmpty())
126 517 : return;
127 :
128 : // Delete the route and add with new local ASN
129 560 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
130 560 : for (PublishedRTargetRoutes::const_iterator it = rtarget_routes_.begin();
131 5927 : it != rtarget_routes_.end(); it++) {
132 5367 : RTargetRouteOp(old_local_asn, it->first, NULL, false);
133 5367 : RTargetRouteOp(local_autonomous_system(), it->first, attr, true);
134 : }
135 560 : }
136 :
137 57905 : void BgpXmppRTargetManager::AddNewRTargetRoute(RoutingInstance *rtinstance,
138 : const RouteTarget &rtarget, BgpAttrPtr attr) {
139 57905 : PublishedRTargetRoutes::iterator rt_loc = rtarget_routes_.find(rtarget);
140 57905 : if (rt_loc == rtarget_routes_.end()) {
141 : pair<PublishedRTargetRoutes::iterator, bool> ret =
142 31019 : rtarget_routes_.insert(make_pair(rtarget, RoutingInstanceList()));
143 :
144 31019 : rt_loc = ret.first;
145 :
146 : // Send rtarget route ADD
147 31019 : RTargetRouteOp(local_autonomous_system(), rtarget, attr, true);
148 : }
149 57905 : rt_loc->second.insert(rtinstance);
150 57905 : }
151 :
152 4440 : void BgpXmppRTargetManager::DeleteRTargetRoute(
153 : RoutingInstance *rtinstance, const RouteTarget &rtarget) {
154 4440 : PublishedRTargetRoutes::iterator rt_loc = rtarget_routes_.find(rtarget);
155 4440 : assert(rt_loc != rtarget_routes_.end());
156 4440 : assert(rt_loc->second.erase(rtinstance));
157 4440 : if (rt_loc->second.empty()) {
158 3179 : rtarget_routes_.erase(rtarget);
159 : // Send rtarget route DELETE
160 3179 : RTargetRouteOp(local_autonomous_system(), rtarget, NULL, false);
161 : }
162 4440 : }
163 :
164 1324 : void BgpXmppRTargetManager::RoutingInstanceCallback(
165 : RoutingInstance *rt_instance, RouteTargetList *targets) {
166 : // Import list in the routing instance
167 1324 : const RouteTargetList &new_list = rt_instance->GetImportList();
168 :
169 : // Previous route target list for which the rtarget route was added
170 1324 : RouteTargetList *current = targets;
171 1324 : RouteTargetList::iterator cur_next_it, cur_it;
172 1324 : cur_it = cur_next_it = current->begin();
173 1324 : RouteTargetList::const_iterator new_it = new_list.begin();
174 :
175 1324 : pair<RouteTargetList::iterator, bool> r;
176 1324 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
177 137770 : while (cur_it != current->end() && new_it != new_list.end()) {
178 136446 : if (*new_it < *cur_it) {
179 219 : r = current->insert(*new_it);
180 219 : assert(r.second);
181 219 : AddNewRTargetRoute(rt_instance, *new_it, attr);
182 219 : new_it++;
183 136227 : } else if (*new_it > *cur_it) {
184 966 : cur_next_it++;
185 966 : DeleteRTargetRoute(rt_instance, *cur_it);
186 966 : current->erase(cur_it);
187 966 : cur_it = cur_next_it;
188 : } else {
189 : // Update
190 135261 : cur_it++;
191 135261 : new_it++;
192 : }
193 136446 : cur_next_it = cur_it;
194 : }
195 1514 : for (; new_it != new_list.end(); ++new_it) {
196 190 : r = current->insert(*new_it);
197 190 : assert(r.second);
198 190 : AddNewRTargetRoute(rt_instance, *new_it, attr);
199 : }
200 1324 : for (cur_next_it = cur_it;
201 1324 : cur_it != current->end();
202 0 : cur_it = cur_next_it) {
203 0 : cur_next_it++;
204 0 : DeleteRTargetRoute(rt_instance, *cur_it);
205 0 : current->erase(cur_it);
206 : }
207 1324 : }
208 :
209 861 : void BgpXmppRTargetManager::UpdateRouteTargetRouteFlag(
210 : RoutingInstance *routing_instance, const RouteTargetList &targets,
211 : uint32_t flags) const {
212 861 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
213 9343 : BOOST_FOREACH(RouteTarget rtarget, targets) {
214 : // Update route target route [llgr-]stale flag status.
215 4241 : RTargetRouteOp(local_autonomous_system(), rtarget, attr, true, flags);
216 : }
217 861 : }
218 :
219 6180 : void BgpXmppRTargetManager::Close() {
220 6180 : if (rtarget_routes_.empty())
221 2870 : return;
222 :
223 3310 : for (PublishedRTargetRoutes::iterator it = rtarget_routes_.begin();
224 31114 : it != rtarget_routes_.end(); it++) {
225 27804 : RTargetRouteOp(local_autonomous_system(), it->first, NULL, false);
226 : }
227 3310 : rtarget_routes_.clear();
228 : }
229 :
230 252 : void BgpXmppRTargetManager::Stale(const RouteTargetList &targets) const {
231 252 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
232 :
233 : // Update route targets to clear STALE flag.
234 2796 : BOOST_FOREACH(RouteTarget rtarget, targets) {
235 : PublishedRTargetRoutes::const_iterator rt_loc =
236 1272 : rtarget_routes_.find(rtarget);
237 1272 : assert(rt_loc != rtarget_routes_.end());
238 :
239 : // Send rtarget route ADD
240 1272 : RTargetRouteOp(local_autonomous_system(), rtarget, attr, true);
241 : }
242 252 : }
243 :
244 : // Add/Delete rtarget route for import route target of the routing instance.
245 15021 : void BgpXmppRTargetManager::PublishRTargetRoute(RoutingInstance *rt_instance,
246 : bool add_change) {
247 15021 : if (IsSubscriptionEmpty())
248 72 : return;
249 :
250 14949 : if (add_change) {
251 129043 : BOOST_FOREACH(RouteTarget rtarget, GetSubscribedRTargets(rt_instance)) {
252 57496 : AddNewRTargetRoute(rt_instance, rtarget, GetRouteTargetRouteAttr());
253 : }
254 : } else {
255 7846 : BOOST_FOREACH(RouteTarget rtarget, GetSubscribedRTargets(rt_instance)) {
256 3474 : DeleteRTargetRoute(rt_instance, rtarget);
257 : }
258 : }
259 : }
260 :
261 1900 : void BgpXmppRTargetManager::FillInfo(BgpNeighborRoutingInstance *instance,
262 : const RouteTargetList &targets) const {
263 1900 : vector<string> import_targets;
264 13300 : BOOST_FOREACH(RouteTarget rt, targets) {
265 5700 : import_targets.push_back(rt.ToString());
266 : }
267 1900 : instance->set_import_targets(import_targets);
268 1900 : }
|