Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef SRC_BGP_BGP_UPDATE_MONITOR_H_ 6 : #define SRC_BGP_BGP_UPDATE_MONITOR_H_ 7 : 8 : #include <boost/function.hpp> 9 : 10 : #include <algorithm> 11 : #include <vector> 12 : 13 : #include "base/util.h" 14 : 15 : class AdvertiseSList; 16 : class DBEntryBase; 17 : struct DBState; 18 : class RibOut; 19 : class RibPeerSet; 20 : class RouteState; 21 : class RouteUpdate; 22 : class UpdateEntry; 23 : class UpdateInfo; 24 : class UpdateInfoSList; 25 : class UpdateList; 26 : class UpdateQueue; 27 : 28 : // 29 : // This class implements an encapsulator for a RouteUpdate which grants the 30 : // user the right to modify the update without holding a lock on the monitor. 31 : // The user must go through the RouteUpdateMonitor and the UpdateQueue to 32 : // remove the RouteUpdate from the UpdateQueue. 33 : // 34 : // A RouteUpdatePtr with a NULL RouteUpdate indicates either the end of an 35 : // UpdateQueue or the presence of an UpdateMarker. 36 : // 37 : // A RouteUpdatePtr is typically used by bgp::SendUpdate task that's dequeuing 38 : // updates from the UpdateQueue. 39 : // 40 : // Movable semantics implemented in c++03. 41 : // 42 : class RouteUpdatePtr { 43 : public: 44 : struct Proxy { 45 937343 : Proxy() : rt_update(NULL) { 46 937343 : } 47 : RouteUpdate *rt_update; 48 : }; 49 2136593 : RouteUpdatePtr() : rt_update_(NULL) { 50 2136593 : } 51 : RouteUpdatePtr(RouteUpdate *rt_update); 52 419 : RouteUpdatePtr(RouteUpdatePtr &rhs) : rt_update_(NULL) { 53 419 : swap(rhs); 54 419 : } 55 937294 : RouteUpdatePtr(Proxy rhs) : rt_update_(rhs.rt_update) { 56 937294 : } 57 : ~RouteUpdatePtr(); 58 : 59 1244887 : RouteUpdate *operator->() { return rt_update_; } 60 5240430 : RouteUpdate *get() { return rt_update_; } 61 : 62 937000 : RouteUpdatePtr &operator=(RouteUpdatePtr &rhs) { 63 937000 : swap(rhs); 64 936985 : return *this; 65 : } 66 : 67 937185 : RouteUpdatePtr &operator=(Proxy rhs) { 68 937185 : RouteUpdatePtr tmp(rhs); 69 937297 : swap(tmp); 70 1874565 : return *this; 71 937287 : } 72 : 73 918246 : RouteUpdate *release() { 74 918246 : RouteUpdate *rt_update = rt_update_; 75 918246 : RouteUpdatePtr tmp; 76 918244 : tmp.swap(*this); 77 1836432 : return rt_update; 78 918222 : } 79 : 80 2792668 : void swap(RouteUpdatePtr &rhs) { 81 2792668 : std::swap(rt_update_, rhs.rt_update_); 82 2792522 : } 83 : 84 937326 : operator Proxy() { 85 937326 : Proxy proxy; 86 937331 : std::swap(proxy.rt_update, rt_update_); 87 937307 : return proxy; 88 : } 89 : 90 : private: 91 : RouteUpdate *rt_update_; 92 : }; 93 : 94 : // 95 : // This implements the interface between the export module which generates 96 : // updates (using the db::DBTable Task) and the update sender module which 97 : // consumes them (using the bgp::SendUpdate Task). Both export processing 98 : // and update sender run concurrently under multiple table shards. 99 : // TaskPolicy configuration ensures that they don't run in parallel for the 100 : // same same shard. 101 : // 102 : class RibUpdateMonitor { 103 : public: 104 : typedef boost::function<bool(const RouteUpdate *)> UpdateCmp; 105 : typedef std::vector<UpdateQueue *> QueueVec; 106 : 107 : explicit RibUpdateMonitor(RibOut *ribout, QueueVec *queue_vec); 108 : 109 : // Used by export module to obtain exclusive access to the DB state. 110 : // If an update is currently present and the comparison function 111 : // returns true, it is considered a duplicate and the function returns 112 : // NULL. Otherwise the update is dequeued and returned. 113 : DBState *GetDBStateAndDequeue(DBEntryBase *db_entry, 114 : UpdateCmp cmp, 115 : bool *duplicate); 116 : 117 : // Fill the mcurrent and mscheduled parameters with the contents of the 118 : // advertised bitmask (history) plus and updates that may be enqueue in 119 : // the specified queue. Returns true if there is an update currently 120 : // enqueued. False otherwise. 121 : bool GetPeerSetCurrentAndScheduled(DBEntryBase *db_entry, 122 : int queue_id, 123 : RibPeerSet *mcurrent, 124 : RibPeerSet *mscheduled); 125 : 126 : // Used by the export module to enqueue/dequeue updates. 127 : bool EnqueueUpdate(DBEntryBase *db_entry, 128 : RouteUpdate *rt_update, 129 : UpdateList *uplist = NULL); 130 : void DequeueUpdate(RouteUpdate *rt_update); 131 : 132 : 133 : // Merge this new update into the existing state. 134 : bool MergeUpdate(DBEntryBase *db_entry, RouteUpdate *rt_update); 135 : 136 : // Cancel scheduled updates for the route and/or remove any current 137 : // advertised state. 138 : void ClearPeerSetCurrentAndScheduled(DBEntryBase *db_entry, 139 : const RibPeerSet &mleave); 140 : 141 : // Used by the update dequeue process to retrieve an update. 142 : RouteUpdatePtr GetNextUpdate(int queue_id, UpdateEntry *upentry); 143 : 144 : // Used by the update dequeue process to retrieve the next entry in the 145 : // queue. If this is an update, it returns the pointer. 146 : RouteUpdatePtr GetNextEntry(int queue_id, UpdateEntry *upentry, 147 : UpdateEntry **next_upentry_p); 148 : 149 : // Used when iterating through updates with the same attribute. 150 : RouteUpdatePtr GetAttrNext(int queue_id, UpdateInfo *current_uinfo, 151 : UpdateInfo **next_uinfo_p); 152 : 153 : void SetEntryState(DBEntryBase *db_entry, DBState *dbstate); 154 : void ClearEntryState(DBEntryBase *db_entry); 155 : 156 : private: 157 : // Helper functions for GetRouteStateAndDequeue 158 : DBState *GetRouteUpdateAndDequeue(DBEntryBase *db_entry, 159 : RouteUpdate *rt_update, 160 : UpdateCmp cmp, bool *duplicate); 161 : DBState *GetUpdateListAndDequeue(DBEntryBase *db_entry, 162 : UpdateList *uplist); 163 : 164 : // Helper functions for MergeUpdate 165 : bool RouteStateMergeUpdate(DBEntryBase *db_entry, 166 : RouteUpdate *rt_update, 167 : RouteState *rstate); 168 : bool RouteUpdateMergeUpdate(DBEntryBase *db_entry, 169 : RouteUpdate *rt_update, 170 : RouteUpdate *current_rt_update); 171 : bool UpdateListMergeUpdate(DBEntryBase *db_entry, 172 : RouteUpdate *rt_update, 173 : UpdateList *uplist); 174 : 175 : // Helper functions for ClearPeerSetCurrentAndScheduled 176 : void AdvertiseSListClearBits(AdvertiseSList &adv_slist, 177 : const RibPeerSet &clear); 178 : void UpdateInfoSListClearBits(UpdateInfoSList &uinfo_slist, 179 : const RibPeerSet &clear); 180 : void RouteStateClearPeerSet(DBEntryBase *db_entry, 181 : RouteState *rstate, const RibPeerSet &mleave); 182 : bool RouteUpdateClearPeerSet(DBEntryBase *db_entry, 183 : RouteUpdate *rt_update, const RibPeerSet &mleave); 184 : bool UpdateListClearPeerSet(DBEntryBase *db_entry, 185 : UpdateList *uplist, const RibPeerSet &mleave); 186 : 187 : RibOut *ribout_; 188 : QueueVec *queue_vec_; 189 : 190 : DISALLOW_COPY_AND_ASSIGN(RibUpdateMonitor); 191 : }; 192 : 193 : #endif // SRC_BGP_BGP_UPDATE_MONITOR_H_