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