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 10063 : BgpXmppRTargetManager::BgpXmppRTargetManager(BgpXmppChannel *bgp_xmpp_channel) :
23 10063 : bgp_xmpp_channel_(bgp_xmpp_channel) {
24 10063 : }
25 :
26 20108 : BgpXmppRTargetManager::~BgpXmppRTargetManager() {
27 20108 : }
28 :
29 15938 : bool BgpXmppRTargetManager::IsSubscriptionEmpty() const {
30 15938 : return bgp_xmpp_channel_->IsSubscriptionEmpty();
31 : }
32 :
33 7913 : bool BgpXmppRTargetManager::IsSubscriptionGrStale(
34 : RoutingInstance *instance) const {
35 7913 : return bgp_xmpp_channel_->IsSubscriptionGrStale(instance);
36 : }
37 :
38 7913 : bool BgpXmppRTargetManager::IsSubscriptionLlgrStale(
39 : RoutingInstance *instance) const {
40 7913 : return bgp_xmpp_channel_->IsSubscriptionLlgrStale(instance);
41 : }
42 :
43 42487 : bool BgpXmppRTargetManager::delete_in_progress() const {
44 42487 : return bgp_xmpp_channel_->delete_in_progress();
45 : }
46 :
47 79467 : const IPeer *BgpXmppRTargetManager::Peer() const {
48 79467 : return bgp_xmpp_channel_->Peer();
49 : }
50 :
51 79467 : void BgpXmppRTargetManager::Enqueue(DBRequest *req) const {
52 : RoutingInstanceMgr *instance_mgr =
53 79467 : bgp_xmpp_channel_->bgp_server()->routing_instance_mgr();
54 79467 : RoutingInstance *master = instance_mgr->GetDefaultRoutingInstance();
55 79467 : BgpTable *table = master->GetTable(Address::RTARGET);
56 79467 : assert(table);
57 79467 : table->Enqueue(req);
58 79467 : }
59 :
60 60429 : BgpAttrPtr BgpXmppRTargetManager::GetRouteTargetRouteAttr() const {
61 60429 : BgpAttrSpec attrs;
62 60429 : BgpAttrNextHop nexthop(bgp_xmpp_channel_->bgp_server()->bgp_identifier());
63 60429 : attrs.push_back(&nexthop);
64 60428 : BgpAttrOrigin origin(BgpAttrOrigin::IGP);
65 60428 : attrs.push_back(&origin);
66 120858 : return bgp_xmpp_channel_->bgp_server()->attr_db()->Locate(attrs);
67 60429 : }
68 :
69 74529 : int BgpXmppRTargetManager::local_autonomous_system() const {
70 74529 : return bgp_xmpp_channel_->bgp_server()->local_autonomous_system();
71 : }
72 :
73 : const BgpXmppRTargetManager::RouteTargetList &
74 14879 : BgpXmppRTargetManager::GetSubscribedRTargets(RoutingInstance *instance) const {
75 14879 : return bgp_xmpp_channel_->GetSubscribedRTargets(instance);
76 : }
77 :
78 38318 : uint32_t BgpXmppRTargetManager::GetRTargetRouteFlag(
79 : const RouteTarget &rtarget) const {
80 : PublishedRTargetRoutes::const_iterator rt_loc =
81 38318 : rtarget_routes_.find(rtarget);
82 38318 : 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 7299 : uint32_t flags = BgpPath::Stale | BgpPath::LlgrStale;
87 15962 : BOOST_FOREACH(RoutingInstance *routing_instance, rt_loc->second) {
88 7973 : if (!IsSubscriptionGrStale(routing_instance))
89 7283 : flags &= ~BgpPath::Stale;
90 7973 : if (!IsSubscriptionLlgrStale(routing_instance))
91 7953 : flags &= ~BgpPath::LlgrStale;
92 7973 : if (!flags)
93 7283 : break;
94 : }
95 :
96 7299 : return flags;
97 : }
98 :
99 79575 : void BgpXmppRTargetManager::RTargetRouteOp(as_t asn,
100 : const RouteTarget &rtarget,
101 : BgpAttrPtr attr, bool add_change,
102 : uint32_t flags) const {
103 79575 : if (add_change && delete_in_progress())
104 0 : return;
105 :
106 79575 : DBRequest req;
107 79575 : RTargetPrefix rt_prefix(asn, rtarget);
108 79575 : req.key.reset(new RTargetTable::RequestKey(rt_prefix, Peer()));
109 79575 : if (add_change) {
110 : // Find correct rtarget route flags if not already known.
111 42559 : if (!flags)
112 38318 : flags = GetRTargetRouteFlag(rtarget);
113 42559 : req.data.reset(new RTargetTable::RequestData(attr, flags, 0, 0, 0));
114 42559 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
115 : } else {
116 37016 : req.oper = DBRequest::DB_ENTRY_DELETE;
117 : }
118 79575 : Enqueue(&req);
119 79575 : }
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 455 : return;
125 1077 : if (IsSubscriptionEmpty())
126 455 : return;
127 :
128 : // Delete the route and add with new local ASN
129 622 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
130 622 : for (PublishedRTargetRoutes::const_iterator it = rtarget_routes_.begin();
131 6655 : it != rtarget_routes_.end(); it++) {
132 6033 : RTargetRouteOp(old_local_asn, it->first, NULL, false);
133 6033 : RTargetRouteOp(local_autonomous_system(), it->first, attr, true);
134 : }
135 622 : }
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 4449 : void BgpXmppRTargetManager::DeleteRTargetRoute(
153 : RoutingInstance *rtinstance, const RouteTarget &rtarget) {
154 4449 : PublishedRTargetRoutes::iterator rt_loc = rtarget_routes_.find(rtarget);
155 4449 : assert(rt_loc != rtarget_routes_.end());
156 4449 : assert(rt_loc->second.erase(rtinstance));
157 4449 : if (rt_loc->second.empty()) {
158 3188 : rtarget_routes_.erase(rtarget);
159 : // Send rtarget route DELETE
160 3188 : RTargetRouteOp(local_autonomous_system(), rtarget, NULL, false);
161 : }
162 4449 : }
163 :
164 1325 : void BgpXmppRTargetManager::RoutingInstanceCallback(
165 : RoutingInstance *rt_instance, RouteTargetList *targets) {
166 : // Import list in the routing instance
167 1325 : const RouteTargetList &new_list = rt_instance->GetImportList();
168 :
169 : // Previous route target list for which the rtarget route was added
170 1325 : RouteTargetList *current = targets;
171 1325 : RouteTargetList::iterator cur_next_it, cur_it;
172 1325 : cur_it = cur_next_it = current->begin();
173 1325 : RouteTargetList::const_iterator new_it = new_list.begin();
174 :
175 1325 : pair<RouteTargetList::iterator, bool> r;
176 1325 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
177 137774 : while (cur_it != current->end() && new_it != new_list.end()) {
178 136449 : 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 136230 : } 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 135264 : cur_it++;
191 135264 : new_it++;
192 : }
193 136449 : cur_next_it = cur_it;
194 : }
195 1515 : 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 1325 : for (cur_next_it = cur_it;
201 1325 : 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 1325 : }
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 6181 : void BgpXmppRTargetManager::Close() {
220 6181 : if (rtarget_routes_.empty())
221 2874 : return;
222 :
223 3307 : for (PublishedRTargetRoutes::iterator it = rtarget_routes_.begin();
224 31102 : it != rtarget_routes_.end(); it++) {
225 27795 : RTargetRouteOp(local_autonomous_system(), it->first, NULL, false);
226 : }
227 3307 : rtarget_routes_.clear();
228 : }
229 :
230 251 : void BgpXmppRTargetManager::Stale(const RouteTargetList &targets) const {
231 251 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
232 :
233 : // Update route targets to clear STALE flag.
234 2783 : BOOST_FOREACH(RouteTarget rtarget, targets) {
235 : PublishedRTargetRoutes::const_iterator rt_loc =
236 1266 : rtarget_routes_.find(rtarget);
237 1266 : assert(rt_loc != rtarget_routes_.end());
238 :
239 : // Send rtarget route ADD
240 1266 : RTargetRouteOp(local_autonomous_system(), rtarget, attr, true);
241 : }
242 251 : }
243 :
244 : // Add/Delete rtarget route for import route target of the routing instance.
245 15022 : void BgpXmppRTargetManager::PublishRTargetRoute(RoutingInstance *rt_instance,
246 : bool add_change) {
247 15022 : if (IsSubscriptionEmpty())
248 72 : return;
249 :
250 14951 : if (add_change) {
251 129042 : BOOST_FOREACH(RouteTarget rtarget, GetSubscribedRTargets(rt_instance)) {
252 57496 : AddNewRTargetRoute(rt_instance, rtarget, GetRouteTargetRouteAttr());
253 : }
254 : } else {
255 7867 : BOOST_FOREACH(RouteTarget rtarget, GetSubscribedRTargets(rt_instance)) {
256 3483 : 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 : }
|