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