Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 : #ifndef vnsw_agent_interface_hpp
6 : #define vnsw_agent_interface_hpp
7 :
8 : /////////////////////////////////////////////////////////////////////////////
9 : // Agent supports multiple type of interface. Class Interface is defines
10 : // common attributes of all interfaces. All interfaces derive from the base
11 : // Interface class
12 : /////////////////////////////////////////////////////////////////////////////
13 :
14 : #include <mutex>
15 :
16 : #include <boost/optional.hpp>
17 : #include <cmn/agent_cmn.h>
18 : #include <cmn/index_vector.h>
19 : #include <oper/oper_db.h>
20 : #include <oper/interface_os_params.h>
21 :
22 : struct InterfaceData;
23 : class VmInterface;
24 : class IFMapDependencyManager;
25 :
26 : class Interface : AgentRefCount<Interface>, public AgentOperDBEntry {
27 : public:
28 : // Type of interfaces supported
29 : enum Type {
30 : INVALID,
31 : // Represents the physical ethernet port. Can be LAG interface also
32 : PHYSICAL,
33 : // Remote Physical interface
34 : REMOTE_PHYSICAL,
35 : // Logical interface
36 : LOGICAL,
37 : // Interface in the virtual machine
38 : VM_INTERFACE,
39 : // The inet interfaces created in host-os
40 : // Example interfaces:
41 : // vhost0 in case of KVM
42 : // xap0 in case of XEN
43 : // vgw in case of Simple Gateway
44 : INET,
45 : // pkt0 interface used to exchange packets between vrouter and agent
46 : PACKET
47 : };
48 :
49 : enum Trace {
50 : ADD,
51 : DEL,
52 : ACTIVATED,
53 : DEACTIVATED,
54 : FLOATING_IP_CHANGE,
55 : SERVICE_CHANGE,
56 : };
57 :
58 : enum MirrorDirection {
59 : MIRROR_RX_TX,
60 : MIRROR_RX,
61 : MIRROR_TX,
62 : UNKNOWN,
63 : };
64 :
65 : enum Transport {
66 : TRANSPORT_INVALID,
67 : TRANSPORT_VIRTUAL,
68 : TRANSPORT_ETHERNET,
69 : TRANSPORT_SOCKET,
70 : TRANSPORT_PMD
71 : };
72 :
73 : static const uint32_t kInvalidIndex = 0xFFFFFFFF;
74 :
75 : Interface(Type type, const boost::uuids::uuid &uuid,
76 : const std::string &name, VrfEntry *vrf, bool os_oper_state,
77 : const boost::uuids::uuid &logical_router_uuid);
78 : virtual ~Interface();
79 :
80 : // DBEntry virtual function. Must be implemented by derived interfaces
81 : virtual KeyPtr GetDBRequestKey() const = 0;
82 : //DBEntry virtual function. Implmeneted in base class since its common
83 : //for all interfaces
84 : virtual void SetKey(const DBRequestKey *key);
85 :
86 : // virtual functions for specific interface types
87 : virtual bool CmpInterface(const DBEntry &rhs) const = 0;
88 0 : virtual bool Delete(const DBRequest *req) { return true; }
89 7 : virtual void Add() { }
90 : virtual void SendTrace(const AgentDBTable *table, Trace event) const;
91 : virtual void GetOsParams(Agent *agent);
92 : void SetPciIndex(Agent *agent, size_t index);
93 :
94 : // DBEntry comparator virtual function
95 131008 : bool IsLess(const DBEntry &rhs) const {
96 131008 : const Interface &intf = static_cast<const Interface &>(rhs);
97 131008 : if (type_ != intf.type_) {
98 4039 : return type_ < intf.type_;
99 : }
100 :
101 126969 : return CmpInterface(rhs);
102 : }
103 :
104 : uint32_t vrf_id() const;
105 193 : uint32_t GetRefCount() const {
106 193 : return AgentRefCount<Interface>::GetRefCount();
107 : }
108 :
109 : bool DBEntrySandesh(Sandesh *sresp, std::string &name) const;
110 :
111 : // Tunnelled packets are expected on PHYSICAL interfaces only
112 78 : bool IsTunnelEnabled() const { return (type_ == PHYSICAL);}
113 :
114 : // Accessor methods
115 82052 : Type type() const {return type_;}
116 20925 : const boost::uuids::uuid &GetUuid() const {return uuid_;}
117 46460 : const std::string &name() const {return os_params_.name_;}
118 19510 : VrfEntry *vrf() const {return vrf_.get();}
119 10061 : bool ipv4_active() const {return ipv4_active_;}
120 846 : bool ipv6_active() const {return ipv6_active_;}
121 2407 : bool is_hc_active() const { return is_hc_active_; }
122 6034 : bool metadata_ip_active() const {return metadata_ip_active_;}
123 1398 : bool metadata_l2_active() const {return metadata_l2_active_;}
124 : bool ip_active(Address::Family family) const;
125 4513 : bool l2_active() const {return l2_active_;}
126 16080 : const uint32_t id() const {return id_;}
127 1423 : bool dhcp_enabled() const {return dhcp_enabled_;}
128 1565 : bool dhcp_enabled_v6() const {return dhcp_enabled_v6_;}
129 0 : bool dns_enabled() const {return dns_enabled_;}
130 6872 : uint32_t label() const {return label_;}
131 1679 : uint32_t l2_label() const {return l2_label_;}
132 : bool IsL2LabelValid(uint32_t label) const { return (label_ == label);}
133 26498 : uint32_t os_index() const {return os_params_.os_index_;}
134 309 : const MacAddress &mac() const {return os_params_.mac_;}
135 10842 : bool os_oper_state() const { return os_params_.os_oper_state_; }
136 : bool admin_state() const { return admin_state_; }
137 : // Used only for test code
138 15 : void set_test_oper_state(bool val) { test_oper_state_ = val; }
139 : void set_flow_key_nh(const NextHop *nh) { flow_key_nh_ = nh;}
140 24941 : const NextHop* flow_key_nh() const {return flow_key_nh_.get();}
141 2656 : Interface::Transport transport() const { return transport_;}
142 : bool IsUveActive() const;
143 2989 : const AgentQosConfig* qos_config() const {
144 2989 : return qos_config_.get();
145 : }
146 : void UpdateOperStateOfSubIntf(const InterfaceTable *table);
147 : bool NeedDefaultOsOperStateDisabled(Agent *agent) const;
148 12907 : boost::optional<InterfaceOsParams::IfGuid> os_guid() const { return os_params_.os_guid_; }
149 2311 : const boost::uuids::uuid &logical_router_uuid() const {
150 2311 : return logical_router_uuid_;
151 : }
152 0 : void set_logical_router_uuid(const boost::uuids::uuid &logical_router_uuid) {
153 0 : logical_router_uuid_ = logical_router_uuid;
154 0 : }
155 :
156 2 : InterfaceOsParams get_os_params() {
157 2 : return os_params_;
158 : }
159 :
160 : protected:
161 : void SetItfSandeshData(ItfSandeshData &data) const;
162 : virtual void ObtainOsSpecificParams(const std::string &name, Agent *agent);
163 :
164 : Type type_;
165 : boost::uuids::uuid uuid_;
166 : VrfEntryRef vrf_;
167 : uint32_t label_;
168 : uint32_t l2_label_;
169 : bool ipv4_active_;
170 : bool ipv6_active_;
171 : // if interface is marked active by health check
172 : bool is_hc_active_;
173 : // interface has metadata ip active
174 : bool metadata_ip_active_;
175 : bool metadata_l2_active_;
176 : bool l2_active_;
177 : size_t id_;
178 : bool dhcp_enabled_;
179 : bool dhcp_enabled_v6_;
180 : bool dns_enabled_;
181 : bool admin_state_;
182 : // Used only for test code
183 : bool test_oper_state_;
184 : //Reference to nexthop, whose index gets used as key in
185 : //flow lookup for traffic ingressing from this interface
186 : //packet interface and bridge interface will not have this
187 : //reference set.
188 : NextHopConstRef flow_key_nh_;
189 : Transport transport_;
190 : AgentQosConfigConstRef qos_config_;
191 : struct InterfaceOsParams os_params_;
192 : boost::uuids::uuid logical_router_uuid_;
193 :
194 : private:
195 : friend class InterfaceTable;
196 : InterfaceTable *table_;
197 : DISALLOW_COPY_AND_ASSIGN(Interface);
198 : };
199 :
200 : // Common key for all interfaces.
201 : struct InterfaceKey : public AgentOperDBKey {
202 8040 : InterfaceKey(const InterfaceKey &rhs) {
203 8040 : type_ = rhs.type_;
204 8040 : uuid_ = rhs.uuid_;
205 8040 : name_ = rhs.name_;
206 8040 : }
207 :
208 53795 : InterfaceKey(AgentKey::DBSubOperation sub_op, Interface::Type type,
209 : const boost::uuids::uuid &uuid,
210 53795 : const std::string &name, bool is_mcast) :
211 53795 : AgentOperDBKey(sub_op), type_(type), uuid_(uuid), name_(name) {
212 53795 : }
213 :
214 : void Init(Interface::Type type, const boost::uuids::uuid &intf_uuid,
215 : const std::string &name) {
216 : type_ = type;
217 : uuid_ = intf_uuid;
218 : name_ = name;
219 : }
220 :
221 542890 : bool IsLess(const InterfaceKey &rhs) const {
222 542890 : if (type_ != rhs.type_) {
223 68 : return type_ < rhs.type_;
224 : }
225 :
226 542822 : if (uuid_ != rhs.uuid_) {
227 56740 : return uuid_ < rhs.uuid_;
228 : }
229 :
230 486082 : return name_ < rhs.name_;
231 : }
232 :
233 267415 : bool IsEqual(const InterfaceKey &rhs) const {
234 267415 : if ((IsLess(rhs) == false) && (rhs.IsLess(*this) == false)) {
235 243041 : return true;
236 : }
237 24374 : return false;
238 : }
239 :
240 : // Virtual methods for interface keys
241 : virtual Interface *AllocEntry(const InterfaceTable *table) const = 0;
242 : virtual Interface *AllocEntry(const InterfaceTable *table,
243 : const InterfaceData *data) const = 0;
244 : virtual InterfaceKey *Clone() const = 0;
245 :
246 : Interface::Type type_;
247 : boost::uuids::uuid uuid_;
248 : std::string name_;
249 : };
250 :
251 : // Common data for all interfaces. The data is further derived based on type
252 : // of interfaces
253 : struct InterfaceData : public AgentOperDBData {
254 1763 : InterfaceData(Agent *agent, IFMapNode *node,
255 1763 : Interface::Transport transport) :
256 1763 : AgentOperDBData(agent, node), transport_(transport),
257 1763 : logical_router_uuid_() { }
258 :
259 1746 : void VmPortInit() { vrf_name_ = ""; }
260 6 : void EthInit(const std::string &vrf_name) { vrf_name_ = vrf_name; }
261 2 : void PktInit() { vrf_name_ = ""; }
262 1 : void InetInit(const std::string &vrf_name) { vrf_name_ = vrf_name; }
263 0 : void RemotePhysicalPortInit(const std::string &vrf_name) {
264 0 : vrf_name_ = vrf_name;
265 0 : }
266 :
267 : // This is constant-data. Set only during create and not modified later
268 : std::string vrf_name_;
269 : Interface::Transport transport_;
270 : boost::uuids::uuid logical_router_uuid_;
271 : };
272 :
273 : struct InterfaceQosConfigData : public AgentOperDBData {
274 0 : InterfaceQosConfigData(const Agent *agent, IFMapNode *node,
275 0 : const boost::uuids::uuid &qos_config_uuid):
276 0 : AgentOperDBData(agent, node), qos_config_uuid_(qos_config_uuid) {}
277 :
278 : boost::uuids::uuid qos_config_uuid_;
279 : };
280 :
281 : /////////////////////////////////////////////////////////////////////////////
282 : // Definition of tree containing physical-device-vn entry created by the VMI
283 : //
284 : // Physical-device-vn entries are built from the VM-Interface to VN link
285 : // The table contains physical-device-vn entry for every VM-Interface
286 : /////////////////////////////////////////////////////////////////////////////
287 : struct VmiToPhysicalDeviceVnData {
288 : VmiToPhysicalDeviceVnData(const boost::uuids::uuid &dev,
289 : const boost::uuids::uuid &vn);
290 : ~VmiToPhysicalDeviceVnData();
291 :
292 : VmiToPhysicalDeviceVnData &operator= (VmiToPhysicalDeviceVnData const &rhs);
293 :
294 : boost::uuids::uuid dev_;
295 : boost::uuids::uuid vn_;
296 : };
297 :
298 : typedef std::map<boost::uuids::uuid, VmiToPhysicalDeviceVnData>
299 : VmiToPhysicalDeviceVnTree;
300 : /////////////////////////////////////////////////////////////////////////////
301 : // Interface Table
302 : // Index for interface is maintained using an IndexVector.
303 : /////////////////////////////////////////////////////////////////////////////
304 : class InterfaceTable : public AgentOperDBTable {
305 : public:
306 : struct DhcpSnoopEntry {
307 0 : DhcpSnoopEntry() : addr_(0), config_entry_(false) { }
308 0 : DhcpSnoopEntry(const Ip4Address &addr, bool config_entry) :
309 0 : addr_(addr), config_entry_(config_entry) { }
310 0 : ~DhcpSnoopEntry() { }
311 : Ip4Address addr_;
312 : bool config_entry_;
313 : };
314 :
315 : typedef std::map<const std::string, DhcpSnoopEntry> DhcpSnoopMap;
316 : typedef std::map<const std::string, DhcpSnoopEntry>::iterator DhcpSnoopIterator;
317 :
318 : // Map of VM-Interface UUID to VmiType. VmiType is computed based on the
319 : // config when interface is added. But when VMI is deleted, the VmiType
320 : // cannot be computed. So, store the computed value in this map
321 : // Storing VmiType as int to avoid forward declaration
322 : typedef std::map<boost::uuids::uuid, int> VmiToVmiTypeMap;
323 :
324 : // DNS module is optional. Callback function to keep DNS entry for
325 : // floating ip in-sync. This callback is defined to avoid linking error
326 : // when DNS is not enabled
327 : typedef boost::function<void(VmInterface *, const VnEntry *,
328 : const IpAddress &, bool)> UpdateFloatingIpFn;
329 :
330 : InterfaceTable(DB *db, const std::string &name);
331 4 : virtual ~InterfaceTable() { }
332 :
333 : void Init(OperDB *oper);
334 : static DBTableBase *CreateTable(DB *db, const std::string &name);
335 : void RegisterDBClients(IFMapDependencyManager *dep);
336 :
337 : // DBTable virtual functions
338 : std::unique_ptr<DBEntry> AllocEntry(const DBRequestKey *k) const;
339 25331 : size_t Hash(const DBEntry *entry) const { return 0; }
340 26948 : size_t Hash(const DBRequestKey *key) const { return 0; }
341 : virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args,
342 : const std::string &context);
343 :
344 : DBEntry *OperDBAdd(const DBRequest *req);
345 : bool OperDBOnChange(DBEntry *entry, const DBRequest *req);
346 : bool OperDBDelete(DBEntry *entry, const DBRequest *req);
347 : bool OperDBResync(DBEntry *entry, const DBRequest *req);
348 :
349 : // Config handlers
350 : bool ProcessConfig(IFMapNode *node, DBRequest &req,
351 : const boost::uuids::uuid &u);
352 : bool InterfaceCommonProcessConfig(IFMapNode *node, DBRequest &req,
353 : const boost::uuids::uuid &u);
354 : bool LogicalInterfaceProcessConfig(IFMapNode *node, DBRequest &req,
355 : const boost::uuids::uuid &u);
356 : bool PhysicalInterfaceProcessConfig(IFMapNode *node, DBRequest &req,
357 : const boost::uuids::uuid &u);
358 : bool VmiProcessConfig(IFMapNode *node, DBRequest &req,
359 : const boost::uuids::uuid &u);
360 : bool VmiIFNodeToReq(IFMapNode *node, DBRequest &req,
361 : const boost::uuids::uuid &u);
362 : bool VmiIFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u);
363 : bool LogicalInterfaceIFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u);
364 : bool PhysicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req,
365 : const boost::uuids::uuid &u);
366 : bool LogicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req,
367 : const boost::uuids::uuid &u);
368 : bool RemotePhysicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest
369 : &req, const boost::uuids::uuid &u);
370 : bool IFNodeToReq(IFMapNode *node, DBRequest &req, const boost::uuids::uuid
371 : &u);
372 : bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u);
373 :
374 : // Handle change in VxLan Identifier mode from global-config
375 : void GlobalVrouterConfigChanged();
376 :
377 : InterfaceConstRef FindVmi(const boost::uuids::uuid &u);
378 :
379 : // Helper functions
380 : VrfEntry *FindVrfRef(const std::string &name) const;
381 : VnEntry *FindVnRef(const boost::uuids::uuid &uuid) const;
382 : VmEntry *FindVmRef(const boost::uuids::uuid &uuid) const;
383 : MirrorEntry *FindMirrorRef(const std::string &name) const;
384 :
385 : // Interface index managing routines
386 : void FreeInterfaceId(size_t index);
387 : const Interface *FindInterface(size_t index) const;
388 : Interface *FindInterface(size_t index);
389 :
390 : /// @brief Finds an interface (Interface) to which a given IPv4
391 : /// address belongs to
392 : /// @param ip is the given IPv4 for which interface is looked
393 : /// @return pointer to the found interface or NULL
394 : const Interface *FindInterfaceFromMetadataIp(const Ip4Address &ip) const;
395 :
396 : /// @brief Finds an interface (Interface) to which a given IPv6
397 : /// address belongs to
398 : /// @param ip is the given IPv6 for which interface is looked
399 : /// @return pointer to the found interface or NULL
400 : const Interface *FindInterfaceFromMetadataIp(const Ip6Address &ip) const;
401 :
402 : // Metadata address management routines (IPv4 & IPv6)
403 :
404 : /// @brief Finds information about a virtual machine connected to a
405 : /// given vm interface with a specified link local IP address
406 : /// (both v4 and v6)
407 : /// @param ip is a given link local IP address for which a virtual machine
408 : /// is searched
409 : /// @param vm_ip is a pointer to a string with a primary IP address of
410 : /// the vm interface associated with the virtual machine
411 : /// @param vm_uuid is a pointer to a string with a UUID of the
412 : /// found virtual machine
413 : /// @param vm_project_uuid is a pointer to a string with
414 : /// a project UUID of the found virtual machine
415 : /// @return true if vm interface is found for the given IP address,
416 : /// otherwise returns false
417 : virtual bool FindVmUuidFromMetadataIp(const IpAddress &ip,
418 : std::string *vm_ip,
419 : std::string *vm_uuid,
420 : std::string *vm_project_uuid);
421 :
422 : /// @brief Creates a link between a given interface (Interface) and
423 : /// a given IPv6 address
424 : /// @param intf is a pointer to the interface for the new link
425 : /// @param addr is the IPv6 address for the new link
426 : void LinkVmPortToMetaDataIp(const Interface* intf, const Ip6Address &addr);
427 :
428 : // Dhcp Snoop Map entries
429 : const Ip4Address GetDhcpSnoopEntry(const std::string &ifname);
430 : void DeleteDhcpSnoopEntry(const std::string &ifname);
431 : void AddDhcpSnoopEntry(const std::string &ifname, const Ip4Address &addr);
432 : void AuditDhcpSnoopTable();
433 : void DhcpSnoopSetConfigSeen(const std::string &ifname);
434 :
435 : void set_update_floatingip_cb(UpdateFloatingIpFn fn);
436 : const UpdateFloatingIpFn &update_floatingip_cb() const;
437 : void AddVmiToVmiType(const boost::uuids::uuid &u, int type);
438 : int GetVmiToVmiType(const boost::uuids::uuid &u);
439 : void DelVmiToVmiType(const boost::uuids::uuid &u);
440 :
441 : // Routines managing VMI to physical-device-vn entry
442 : void UpdatePhysicalDeviceVnEntry(const boost::uuids::uuid &vmi,
443 : boost::uuids::uuid &dev,
444 : boost::uuids::uuid &vn,
445 : IFMapNode *vn_node);
446 : void DelPhysicalDeviceVnEntry(const boost::uuids::uuid &vmi);
447 :
448 : // TODO : to remove this
449 2867 : static InterfaceTable *GetInstance() { return interface_table_; }
450 106242 : Agent *agent() const { return agent_; }
451 165 : OperDB *operdb() const { return operdb_; }
452 :
453 : uint32_t vmi_count() const { return vmi_count_; }
454 : void incr_vmi_count() { vmi_count_++; }
455 169 : void decr_vmi_count() { vmi_count_--; }
456 :
457 : uint32_t li_count() const { return li_count_; }
458 : void incr_li_count() { li_count_++; }
459 1 : void decr_li_count() { li_count_--; }
460 :
461 : uint32_t active_vmi_count() const { return active_vmi_count_; }
462 169 : void incr_active_vmi_count() { active_vmi_count_++; }
463 169 : void decr_active_vmi_count() { active_vmi_count_--; }
464 :
465 : uint32_t vmi_ifnode_to_req() const { return vmi_ifnode_to_req_; }
466 : uint32_t li_ifnode_to_req() const { return li_ifnode_to_req_; }
467 : uint32_t pi_ifnode_to_req() const { return pi_ifnode_to_req_; }
468 : //Shutdown
469 : virtual void Clear();
470 : void CreateVhost();
471 : void CreateVhostReq();
472 :
473 : private:
474 : bool L2VmInterfaceWalk(DBTablePartBase *partition,
475 : DBEntryBase *entry);
476 : void VmInterfaceWalkDone(DBTable::DBTableWalkRef walk_ref,
477 : DBTableBase *partition);
478 :
479 : static InterfaceTable *interface_table_;
480 : OperDB *operdb_; // Cached entry
481 : Agent *agent_; // Cached entry
482 : DBTable::DBTableWalkRef global_config_change_walk_ref_;
483 : IndexVector<Interface *> index_table_;
484 :
485 : // On restart, DHCP Snoop entries are read from kernel and updated in the
486 : // ASIO context. Lock used to synchronize
487 : std::mutex dhcp_snoop_mutex_;
488 : DhcpSnoopMap dhcp_snoop_map_;
489 : UpdateFloatingIpFn update_floatingip_cb_;
490 : VmiToVmiTypeMap vmi_to_vmitype_map_;
491 : // Tree of physical-device-vn entries created by VMIs
492 : VmiToPhysicalDeviceVnTree vmi_to_physical_device_vn_tree_;
493 : // Count of type of interfaces
494 : uint32_t vmi_count_;
495 : uint32_t li_count_;
496 : // Count of active vm-interfaces
497 : uint32_t active_vmi_count_;
498 : uint32_t vmi_ifnode_to_req_;
499 : uint32_t li_ifnode_to_req_;
500 : uint32_t pi_ifnode_to_req_;
501 :
502 : DISALLOW_COPY_AND_ASSIGN(InterfaceTable);
503 : };
504 :
505 : #endif // vnsw_agent_interface_hpp
|