Line data Source code
1 : /*
2 : * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #ifndef _VNSW_AGENT_PORT_IPC_PORT_SUBSCRIBE_TABLE_H_
6 : #define _VNSW_AGENT_PORT_IPC_PORT_SUBSCRIBE_TABLE_H_
7 :
8 : #include <map>
9 : #include <memory>
10 : #include <mutex>
11 : #include <vector>
12 : #include <string>
13 : #include <string>
14 : #include <boost/uuid/uuid.hpp>
15 : #include <boost/shared_ptr.hpp>
16 :
17 : #include <base/util.h>
18 : #include <base/address.h>
19 : #include <db/db_table.h>
20 : #include <db/db_entry.h>
21 : #include <vnc_cfg_types.h>
22 :
23 : class InterfaceTable;
24 : class Agent;
25 : struct VmInterfaceConfigData;
26 : class VmiSubscribeEntry;
27 : class VmVnPortSubscribeEntry;
28 : class PortSubscribeEntry;
29 : class PortSubscribeTable;
30 : typedef boost::shared_ptr<PortSubscribeEntry> PortSubscribeEntryPtr;
31 :
32 : /****************************************************************************
33 : * The class is responsible to manage port subscribe/unsubscribe from IPC
34 : * channels.
35 : ****************************************************************************/
36 : class PortSubscribeEntry {
37 : public:
38 : enum Type {
39 : VMPORT,
40 : NAMESPACE,
41 : REMOTE_PORT
42 : };
43 :
44 : PortSubscribeEntry(Type type, const std::string &ifname, int32_t version);
45 : virtual ~PortSubscribeEntry();
46 :
47 : virtual void OnAdd(Agent *agent, PortSubscribeTable *table) const = 0;
48 : virtual void OnDelete(Agent *agent, PortSubscribeTable *table) const = 0;
49 : virtual void Update(const PortSubscribeEntry *rhs);
50 :
51 : static const char *TypeToString(Type type);
52 74 : Type type() const { return type_; }
53 24 : const std::string &ifname() const { return ifname_; }
54 24 : uint32_t version() const { return version_; }
55 :
56 : virtual bool MatchVn(const boost::uuids::uuid &u) const = 0;
57 : virtual const boost::uuids::uuid &vn_uuid() const = 0;
58 : virtual bool MatchVm(const boost::uuids::uuid &u) const = 0;
59 : virtual const boost::uuids::uuid &vm_uuid() const = 0;
60 :
61 : protected:
62 : Type type_;
63 : std::string ifname_;
64 : uint16_t version_;
65 : DISALLOW_COPY_AND_ASSIGN(PortSubscribeEntry);
66 : };
67 :
68 : class VmiSubscribeEntry : public PortSubscribeEntry {
69 : public:
70 : VmiSubscribeEntry(PortSubscribeEntry::Type type, const std::string &ifname,
71 : uint32_t version, const boost::uuids::uuid &vmi_uuid,
72 : const boost::uuids::uuid vm_uuid,
73 : const std::string &vm_name,
74 : const boost::uuids::uuid &vn_uuid,
75 : const boost::uuids::uuid &project_uuid,
76 : const Ip4Address &ip4_addr, const Ip6Address &ip6_addr,
77 : const std::string &mac_addr, uint16_t tx_vlan_id,
78 : uint16_t rx_vlan_id,
79 : uint8_t vhostuser_mode, uint8_t link_state);
80 : ~VmiSubscribeEntry();
81 :
82 : virtual bool MatchVn(const boost::uuids::uuid &u) const;
83 : virtual bool MatchVm(const boost::uuids::uuid &u) const;
84 :
85 : virtual void Update(const PortSubscribeEntry *rhs);
86 : void OnAdd(Agent *agent, PortSubscribeTable *table) const;
87 : void OnDelete(Agent *agent, PortSubscribeTable *table) const;
88 :
89 36 : const boost::uuids::uuid &vmi_uuid() const { return vmi_uuid_; }
90 24 : const boost::uuids::uuid &vm_uuid() const { return vm_uuid_; }
91 24 : const std::string &vm_name() const { return vm_name_; }
92 43 : const boost::uuids::uuid &vn_uuid() const { return vn_uuid_; }
93 24 : const boost::uuids::uuid &project_uuid() const { return project_uuid_; }
94 24 : const Ip4Address &ip4_addr() const { return ip4_addr_; }
95 24 : const Ip6Address &ip6_addr() const { return ip6_addr_; }
96 24 : const std::string &mac_addr() const { return mac_addr_; }
97 24 : uint16_t tx_vlan_id() const { return tx_vlan_id_; }
98 24 : uint16_t rx_vlan_id() const { return rx_vlan_id_; }
99 24 : uint8_t vhostuser_mode() const { return vhostuser_mode_; }
100 12 : uint8_t link_state() const { return link_state_; }
101 0 : void set_link_state(uint8_t value) { link_state_ = value; }
102 : private:
103 : boost::uuids::uuid vmi_uuid_;
104 : boost::uuids::uuid vm_uuid_;
105 : std::string vm_name_;
106 : boost::uuids::uuid vn_uuid_;
107 : boost::uuids::uuid project_uuid_;
108 : Ip4Address ip4_addr_;
109 : Ip6Address ip6_addr_;
110 : std::string mac_addr_;
111 : uint16_t tx_vlan_id_;
112 : uint16_t rx_vlan_id_;
113 : uint8_t vhostuser_mode_;
114 : uint8_t link_state_;
115 : DISALLOW_COPY_AND_ASSIGN(VmiSubscribeEntry);
116 : };
117 :
118 : /****************************************************************************
119 : * In case of container orchestrators like k8s/mesos, we do not get VMI UUID
120 : * in port-subscribe message. Instead, the interface is addressed by
121 : * vm-uuid and vn. The VmVnPortSubscribeEntry class is used for these
122 : * scenarios
123 : ****************************************************************************/
124 : class VmVnPortSubscribeEntry : public PortSubscribeEntry {
125 : public:
126 : VmVnPortSubscribeEntry(PortSubscribeEntry::Type type,
127 : const std::string &ifname, uint32_t version,
128 : const boost::uuids::uuid &vm_uuid,
129 : const boost::uuids::uuid &vn_uuid,
130 : const boost::uuids::uuid &vmi_uuid,
131 : const std::string &vm_name,
132 : const std::string &vm_identifier,
133 : const std::string &vm_ifname,
134 : const std::string &vm_namespace);
135 : ~VmVnPortSubscribeEntry();
136 :
137 : virtual bool MatchVn(const boost::uuids::uuid &u) const;
138 0 : virtual const boost::uuids::uuid &vn_uuid() const { return vn_uuid_; }
139 : virtual bool MatchVm(const boost::uuids::uuid &u) const;
140 0 : virtual const boost::uuids::uuid &vm_uuid() const { return vm_uuid_; }
141 :
142 : virtual void Update(const PortSubscribeEntry *rhs);
143 : void OnAdd(Agent *agent, PortSubscribeTable *table) const;
144 : void OnDelete(Agent *agent, PortSubscribeTable *table) const;
145 :
146 0 : const std::string &vm_name() const { return vm_name_; }
147 0 : const std::string &vm_identifier() const { return vm_identifier_; }
148 0 : const std::string &vm_ifname() const { return vm_ifname_; }
149 0 : const std::string &vm_namespace() const { return vm_namespace_; }
150 0 : void set_vmi_uuid(const boost::uuids::uuid &u) { vmi_uuid_ = u; }
151 0 : const boost::uuids::uuid &vmi_uuid() const { return vmi_uuid_; }
152 : private:
153 : boost::uuids::uuid vm_uuid_;
154 : boost::uuids::uuid vn_uuid_;
155 : std::string vm_name_;
156 : std::string vm_identifier_;
157 : std::string vm_ifname_;
158 : std::string vm_namespace_;
159 : boost::uuids::uuid vmi_uuid_;
160 : DISALLOW_COPY_AND_ASSIGN(VmVnPortSubscribeEntry);
161 : };
162 :
163 : class PortSubscribeTable {
164 : public:
165 : PortSubscribeTable(Agent *agent);
166 : virtual ~PortSubscribeTable();
167 :
168 : struct State : DBState {
169 14 : State() : uuid_() { }
170 28 : ~State() { }
171 :
172 : boost::uuids::uuid uuid_;
173 : };
174 :
175 : struct Cmp {
176 192 : bool operator()(const boost::uuids::uuid &lhs,
177 : const boost::uuids::uuid &rhs) const {
178 192 : return lhs < rhs;
179 : }
180 : };
181 : typedef std::map<boost::uuids::uuid, PortSubscribeEntryPtr, Cmp> VmiTree;
182 : typedef std::map<boost::uuids::uuid, IFMapNode *> UuidToIFNodeTree;
183 :
184 : // trees used for managing vm-vn port subscriptions
185 : // VmiToVmVnTree : The tree from vmi-uuid to corresponding
186 : // vm+vn uuid
187 : // VmVnToVmiTree : Reverse mapping for VmiToVmVnTree. Will be used
188 : // to find VMI when port-subscription message
189 : // Both the tree are built from VmInterfaceConfigData
190 :
191 : struct VmVnUuidEntry {
192 : boost::uuids::uuid vm_uuid_;
193 : boost::uuids::uuid vn_uuid_;
194 : boost::uuids::uuid vmi_uuid_;
195 :
196 122 : VmVnUuidEntry(const boost::uuids::uuid &vm_uuid,
197 : const boost::uuids::uuid &vn_uuid,
198 122 : const boost::uuids::uuid &vmi_uuid) :
199 122 : vm_uuid_(vm_uuid), vn_uuid_(vn_uuid), vmi_uuid_(vmi_uuid) {
200 122 : }
201 : VmVnUuidEntry() :
202 : vm_uuid_(boost::uuids::nil_uuid()),
203 : vn_uuid_(boost::uuids::nil_uuid()),
204 : vmi_uuid_(boost::uuids::nil_uuid()) {
205 : }
206 144 : virtual ~VmVnUuidEntry() { }
207 : };
208 :
209 : struct VmVnUuidEntryCmp {
210 69 : bool operator()(const VmVnUuidEntry &lhs,
211 : const VmVnUuidEntry &rhs) const {
212 69 : if (lhs.vm_uuid_ != rhs.vm_uuid_) {
213 48 : return lhs.vm_uuid_ < rhs.vm_uuid_;
214 : }
215 21 : if (lhs.vn_uuid_ != rhs.vn_uuid_) {
216 0 : return lhs.vn_uuid_ < rhs.vn_uuid_;
217 : }
218 21 : return lhs.vmi_uuid_ < rhs.vmi_uuid_;
219 : }
220 : };
221 :
222 : struct VmiEntry {
223 : boost::uuids::uuid vm_uuid_;
224 : boost::uuids::uuid vn_uuid_;
225 : bool sub_interface_;
226 : boost::uuids::uuid parent_vmi_;
227 : uint16_t vlan_tag_;
228 : std::string mac_;
229 : uint8_t vhostuser_mode_;
230 : autogen::VirtualMachineInterface *vmi_cfg;
231 :
232 4 : VmiEntry() :
233 4 : vm_uuid_(), vn_uuid_(), sub_interface_(), parent_vmi_(),
234 4 : vlan_tag_(), mac_(), vhostuser_mode_() {
235 4 : vmi_cfg = NULL;
236 4 : }
237 : };
238 :
239 : typedef std::map<boost::uuids::uuid, VmiEntry> VmiToVmVnTree;
240 : typedef std::map<VmVnUuidEntry, boost::uuids::uuid, VmVnUuidEntryCmp>
241 : VmVnToVmiTree;
242 : typedef std::map<VmVnUuidEntry, PortSubscribeEntryPtr, VmVnUuidEntryCmp>
243 : VmVnTree;
244 :
245 : void InitDone();
246 : void Shutdown();
247 : IFMapNode *UuidToIFNode(const boost::uuids::uuid &u) const;
248 : void Notify(DBTablePartBase *partition, DBEntryBase *e);
249 : void StaleWalk(uint64_t version);
250 0 : uint32_t Size() const { return vmi_tree_.size(); }
251 :
252 : void AddVmi(const boost::uuids::uuid &u, PortSubscribeEntryPtr entry);
253 : void DeleteVmi(const boost::uuids::uuid &u);
254 : PortSubscribeEntryPtr GetVmi(const boost::uuids::uuid &u) const;
255 :
256 : void AddVmVnPort(const boost::uuids::uuid &vm_uuid,
257 : const boost::uuids::uuid &vn_uuid,
258 : const boost::uuids::uuid &vmi_uuid,
259 : PortSubscribeEntryPtr entry);
260 : void DeleteVmVnPort(const boost::uuids::uuid &vm_uuid,
261 : const boost::uuids::uuid &vn_uuid,
262 : const boost::uuids::uuid &vmi_uuid);
263 : PortSubscribeEntryPtr GetVmVnPortNoLock(const boost::uuids::uuid &vm_uuid,
264 : const boost::uuids::uuid &vn_uuid,
265 : const boost::uuids::uuid &vmi_uuid);
266 : PortSubscribeEntryPtr GetVmVnPort(const boost::uuids::uuid &vm_uuid,
267 : const boost::uuids::uuid &vn_uuid,
268 : const boost::uuids::uuid &vmi_uuid);
269 :
270 : void HandleVmiIfnodeAdd(const boost::uuids::uuid &vmi_uuid,
271 : const VmInterfaceConfigData *data);
272 : void HandleVmiIfnodeDelete(const boost::uuids::uuid &vmi_uuid);
273 :
274 : PortSubscribeEntryPtr Get(const boost::uuids::uuid &vmi_uuid,
275 : const boost::uuids::uuid &vm_uuid,
276 : const boost::uuids::uuid &vn_uuid) const;
277 :
278 : bool VmVnToVmiSetNoLock(const boost::uuids::uuid &vm_uuid,
279 : std::set<boost::uuids::uuid> &vmi_uuid_set) const;
280 : bool VmVnToVmiSet(const boost::uuids::uuid &vm_uuid,
281 : std::set<boost::uuids::uuid> &vmi_uuid_set) const;
282 : const VmiEntry *VmiToEntry(const boost::uuids::uuid &vmi_uuid) const;
283 :
284 : private:
285 : void UpdateVmiIfnodeInfo(const boost::uuids::uuid &vmi_uuid,
286 : const VmInterfaceConfigData *data);
287 : void DeleteVmiIfnodeInfo(const boost::uuids::uuid &vmi_uuid);
288 : private:
289 : friend class SandeshVmiPortSubscribeTask;
290 : friend class SandeshVmVnPortSubscribeTask;
291 : friend class SandeshVmiToVmVnTask;
292 : friend class SandeshVmVnToVmiTask;
293 :
294 : Agent *agent_;
295 : InterfaceTable *interface_table_;
296 : VNController *controller_;
297 : mutable std::mutex mutex_;
298 : VmiTree vmi_tree_;
299 : IFMapAgentTable *vmi_config_table_;
300 : DBTableBase::ListenerId vmi_config_listener_id_;
301 : UuidToIFNodeTree uuid_ifnode_tree_;
302 : VmiToVmVnTree vmi_to_vmvn_tree_;
303 : VmVnToVmiTree vmvn_to_vmi_tree_;
304 : VmVnTree vmvn_subscribe_tree_;
305 : DISALLOW_COPY_AND_ASSIGN(PortSubscribeTable);
306 : };
307 :
308 : #endif // _VNSW_AGENT_PORT_IPC_PORT_SUBSCRIBE_TABLE_H_
|