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