LCOV - code coverage report
Current view: top level - vnsw/agent/oper - physical_interface.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 124 198 62.6 %
Date: 2026-11-09 02:10:49 Functions: 19 26 73.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <boost/uuid/uuid_io.hpp>
       7             : #include <vnc_cfg_types.h>
       8             : #include <cmn/agent_cmn.h>
       9             : 
      10             : #include <net/if.h>
      11             : #include <ifmap/ifmap_node.h>
      12             : #include <cfg/cfg_init.h>
      13             : #include <cfg/cfg_listener.h>
      14             : #include <oper/agent_sandesh.h>
      15             : #include <oper/ifmap_dependency_manager.h>
      16             : #include <oper/interface_common.h>
      17             : #include <oper/physical_device.h>
      18             : #include <oper/nexthop.h>
      19             : #include <oper/config_manager.h>
      20             : 
      21             : #include <vector>
      22             : #include <string>
      23             : 
      24             : using std::string;
      25             : 
      26             : /////////////////////////////////////////////////////////////////////////////
      27             : // PhysicalInterface routines
      28             : /////////////////////////////////////////////////////////////////////////////
      29          68 : PhysicalInterface::PhysicalInterface(const std::string &name,
      30          68 :                            const boost::uuids::uuid &logical_router_uuid) :
      31           0 :     Interface(Interface::PHYSICAL, boost::uuids::nil_uuid(), name, NULL, true,
      32             :               logical_router_uuid),
      33          68 :     persistent_(false), subtype_(INVALID), physical_device_(NULL) {
      34          68 : }
      35             : 
      36         136 : PhysicalInterface::~PhysicalInterface() {
      37         136 : }
      38             : 
      39           3 : PhysicalDevice *PhysicalInterface::physical_device() const {
      40           3 :     return physical_device_.get();
      41             : }
      42             : 
      43           0 : string PhysicalInterface::ToString() const {
      44           0 :     return "PORT <" + name() + ">";
      45             : }
      46             : 
      47         156 : bool PhysicalInterface::CmpInterface(const DBEntry &rhs) const {
      48         156 :     const PhysicalInterface &a = static_cast<const PhysicalInterface &>(rhs);
      49         156 :     return name() < a.name();
      50             : }
      51             : 
      52           9 : DBEntryBase::KeyPtr PhysicalInterface::GetDBRequestKey() const {
      53           9 :     InterfaceKey *key = new PhysicalInterfaceKey(name());
      54           9 :     return DBEntryBase::KeyPtr(key);
      55             : }
      56             : 
      57           6 : bool PhysicalInterface::OnChange(const InterfaceTable *table,
      58             :                                  const PhysicalInterfaceData *data) {
      59           6 :     bool ret = false;
      60             :     const PhysicalInterfaceOsOperStateData *osOperStateData =
      61           6 :         dynamic_cast<const PhysicalInterfaceOsOperStateData *>(data);
      62             : 
      63           6 :     if(osOperStateData) {
      64           0 :         ret = osOperStateData->OnResync(this);
      65             :     }
      66             :     else {
      67             :         // Handle VRF Change
      68           6 :         VrfKey key(data->vrf_name_);
      69           6 :         VrfEntry *new_vrf = static_cast<VrfEntry *>
      70           6 :             (table->agent()->vrf_table()->FindActiveEntry(&key));
      71           6 :         if (new_vrf != vrf_.get()) {
      72           3 :             vrf_.reset(new_vrf);
      73           3 :             ret = true;
      74             : 
      75             :         }
      76             : 
      77             :         PhysicalDevice *dev =
      78           6 :             table->agent()->physical_device_table()->Find(data->device_uuid_);
      79           6 :         if (dev != physical_device_.get()) {
      80           2 :             physical_device_.reset(dev);
      81           2 :             ret = true;
      82             :         }
      83           6 :     }
      84           6 :     return ret;
      85             : }
      86             : 
      87             : bool
      88           0 : PhysicalInterfaceOsOperStateData::OnResync(PhysicalInterface *phy_intf) const
      89             : {
      90           0 :     bool ret = false;
      91           0 :     if(type_ == PhysicalInterfaceOsOperStateData::VR_FABRIC) {
      92           0 :         if(phy_intf->os_params_.os_oper_state_ != oper_state_) {
      93           0 :             phy_intf->os_params_.os_oper_state_ = oper_state_;
      94           0 :             ret = true;
      95             :         }
      96           0 :     } else if(type_ == PhysicalInterfaceOsOperStateData::VR_BOND_SLAVES) {
      97           0 :         PhysicalInterface::Bond_ChildIntf bondIntf;
      98             : 
      99           0 :         bondIntf.intf_name = intf_name;
     100           0 :         bondIntf.intf_drv_name = intf_drv_name;
     101           0 :         bondIntf.intf_status = oper_state_;
     102             :         PhysicalInterface::BondChildIntfMap bond_childIntf_map =
     103           0 :               phy_intf->getBondChildIntfMap();
     104           0 :         bond_childIntf_map[intf_name] = bondIntf;
     105           0 :         phy_intf->setBondChildIntfMap(bond_childIntf_map);
     106           0 :         ret = true;
     107           0 :     }
     108             : 
     109           0 :     return ret;
     110             : }
     111             : 
     112           4 : bool PhysicalInterface::Delete(const DBRequest *req) {
     113           4 :     flow_key_nh_.reset();
     114           4 :     InterfaceNH::DeletePhysicalInterfaceNh(name(), mac());
     115           4 :     return true;
     116             : }
     117             : 
     118           0 : std::string PhysicalInterface::GetPhysicalInterfaceName() const {
     119           0 :     std::size_t pos = name().find_last_of(":");
     120           0 :     if (pos != string::npos) {
     121           0 :         return name().substr(pos + 1);
     122             :     }
     123           0 :     return name();
     124             : }
     125             : 
     126           3 : void PhysicalInterface::PostAdd() {
     127           3 :     InterfaceNH::CreatePhysicalInterfaceNh(name(), mac());
     128             : 
     129           3 :     InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
     130           3 :     Agent *agent = table->agent();
     131             : 
     132           3 :     InterfaceNHKey key(new PhysicalInterfaceKey(name()), false, InterfaceNHFlags::INET4, mac());
     133             :     flow_key_nh_ = static_cast<InterfaceNH *>
     134           3 :         (agent->nexthop_table()->FindActiveEntry(&key));
     135           3 :     assert(flow_key_nh_);
     136             : 
     137             : 
     138           3 :     if (table->agent()->test_mode()) {
     139           3 :         return;
     140             :     }
     141             : 
     142           0 :     std::string interface_name = name();
     143             :     // Interfaces in VMWARE mode and having remote VMs
     144             :     // must be put into promiscuous mode
     145           0 :     if (subtype_ != VMWARE) {
     146           0 :         if (!table->agent()->server_gateway_mode() ||
     147           0 :             subtype_ == PhysicalInterface::FABRIC) {
     148           0 :             return;
     149             :         } else {
     150           0 :             interface_name = GetPhysicalInterfaceName();
     151             :         }
     152             :     }
     153             : 
     154           0 :     int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
     155           0 :     assert(fd >= 0);
     156             : 
     157             :     struct ifreq ifr;
     158           0 :     memset(&ifr, 0, sizeof(ifr));
     159           0 :     strncpy(ifr.ifr_name, interface_name.c_str(), IF_NAMESIZE-1);
     160             : 
     161           0 :     if (ioctl(fd, SIOCGIFFLAGS, (void *)&ifr) < 0) {
     162           0 :         LOG(ERROR, "Error <" << errno << ": " << strerror(errno) <<
     163             :             "> setting promiscuous flag for interface <" << interface_name << ">");
     164           0 :         close(fd);
     165           0 :         return;
     166             :     }
     167             : 
     168           0 :     ifr.ifr_flags |= IFF_PROMISC;
     169           0 :     if (ioctl(fd, SIOCSIFFLAGS, (void *)&ifr) < 0) {
     170           0 :         LOG(ERROR, "Error <" << errno << ": " << strerror(errno) <<
     171             :             "> setting promiscuous flag for interface <" << interface_name << ">");
     172           0 :         close(fd);
     173           0 :         return;
     174             :     }
     175             : 
     176           0 :     close(fd);
     177             : 
     178           3 : }
     179             : 
     180             : /////////////////////////////////////////////////////////////////////////////
     181             : // PhysicalInterfaceKey routines
     182             : /////////////////////////////////////////////////////////////////////////////
     183          63 : PhysicalInterfaceKey::PhysicalInterfaceKey(const std::string &name) :
     184             :     InterfaceKey(AgentKey::ADD_DEL_CHANGE, Interface::PHYSICAL,
     185          63 :                  boost::uuids::nil_uuid(), name, false) {
     186          63 : }
     187             : 
     188          90 : PhysicalInterfaceKey::~PhysicalInterfaceKey() {
     189          90 : }
     190             : 
     191          65 : Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table) const {
     192          65 :     return new PhysicalInterface(name_, boost::uuids::nil_uuid());
     193             : }
     194             : 
     195           3 : Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table,
     196             :                                             const InterfaceData *data) const {
     197           3 :     PhysicalInterface *intf = new PhysicalInterface(name_,
     198           3 :                                                     data->logical_router_uuid_);
     199           3 :     const PhysicalInterfaceData *phy_data =
     200             :         static_cast<const PhysicalInterfaceData *>(data);
     201           3 :     intf->encap_type_ = phy_data->encap_type_;
     202           3 :     intf->no_arp_ = phy_data->no_arp_;
     203           3 :     intf->subtype_ = phy_data->subtype_;
     204           3 :     intf->display_name_ = phy_data->display_name_;
     205           3 :     if (intf->subtype_ == PhysicalInterface::VMWARE ||
     206           3 :         intf->subtype_ == PhysicalInterface::CONFIG) {
     207           1 :         intf->persistent_ = true;
     208             :     }
     209             : 
     210           3 :     intf->OnChange(table, phy_data);
     211           3 :     return intf;
     212             : }
     213             : 
     214           0 : InterfaceKey *PhysicalInterfaceKey::Clone() const {
     215           0 :     return new PhysicalInterfaceKey(name_);
     216             : }
     217             : 
     218             : /////////////////////////////////////////////////////////////////////////////
     219             : // PhysicalInterfaceData routines
     220             : /////////////////////////////////////////////////////////////////////////////
     221           6 : PhysicalInterfaceData::PhysicalInterfaceData(Agent *agent, IFMapNode *node,
     222             :                                              const string &vrf_name,
     223             :                                              PhysicalInterface::SubType subtype,
     224             :                                              PhysicalInterface::EncapType encap,
     225             :                                              bool no_arp,
     226             :                                              const boost::uuids::uuid &device_uuid,
     227             :                                              const string &display_name,
     228             :                                              const Ip4Address &ip,
     229           6 :                                              Interface::Transport transport) :
     230           6 :     InterfaceData(agent, node, transport), subtype_(subtype), encap_type_(encap),
     231           6 :     no_arp_(no_arp), device_uuid_(device_uuid), display_name_(display_name),
     232           6 :     ip_(ip) {
     233           6 :     EthInit(vrf_name);
     234           6 : }
     235             : 
     236             : /////////////////////////////////////////////////////////////////////////////
     237             : // Config handling routines
     238             : /////////////////////////////////////////////////////////////////////////////
     239           6 : static PhysicalInterfaceKey *BuildKey(const std::string &name) {
     240           6 :     return new PhysicalInterfaceKey(name);
     241             : }
     242             : 
     243           9 : bool InterfaceTable::PhysicalInterfaceIFNodeToReq(IFMapNode *node,
     244             :                                                   DBRequest &req,
     245             :                                                   const boost::uuids::uuid &u) {
     246             : 
     247             :     // Enqueue request to config-manager if add/change
     248          16 :     if ((req.oper != DBRequest::DB_ENTRY_DELETE) &&
     249           7 :                             (node->IsDeleted() == false)) {
     250           7 :         agent()->config_manager()->AddPhysicalInterfaceNode(node);
     251           7 :         return false;
     252             :     }
     253             : 
     254             :     autogen::PhysicalInterface *port =
     255           2 :         static_cast <autogen::PhysicalInterface *>(node->GetObject());
     256           2 :     assert(port);
     257             : 
     258             :     // Get the physical-router from FQDN
     259           2 :     string device = "";
     260           2 :     vector<string> elements;
     261           2 :     split(elements, node->name(), boost::is_any_of(":"), boost::token_compress_on);
     262           2 :     if (elements.size() == 3) {
     263           0 :         device = elements[1];
     264             :     }
     265             : 
     266           2 :     if (elements.size() == 3 && device != agent()->agent_name()) {
     267           0 :         if (RemotePhysicalInterfaceIFNodeToReq(node, req, u)) {
     268           0 :             Enqueue(&req);
     269             :         }
     270           0 :         return false;
     271             :     }
     272             : 
     273           2 :     req.key.reset(BuildKey(node->name()));
     274           2 :     req.oper = DBRequest::DB_ENTRY_DELETE;
     275           2 :     return true;
     276           2 : }
     277             : 
     278           4 : bool InterfaceTable::PhysicalInterfaceProcessConfig(IFMapNode *node,
     279             :         DBRequest &req, const boost::uuids::uuid &u) {
     280             : 
     281           4 :     if (node->IsDeleted()) {
     282           0 :         return false;
     283             :     }
     284             : 
     285             :     autogen::PhysicalInterface *port =
     286           4 :         static_cast <autogen::PhysicalInterface *>(node->GetObject());
     287           4 :     assert(port);
     288             : 
     289             :     // Get the physical-router from FQDN
     290           4 :     string device = "";
     291           4 :     vector<string> elements;
     292           4 :     split(elements, node->name(), boost::is_any_of(":"), boost::token_compress_on);
     293           4 :     if (elements.size() == 3) {
     294           0 :         device = elements[1];
     295             :     }
     296             : 
     297             :     // If physical-router does not match agent_name, treat as remote interface
     298           4 :     if (elements.size() == 3 && device != agent()->agent_name()) {
     299           0 :         return RemotePhysicalInterfaceIFNodeToReq(node, req, u);
     300             :     }
     301             : 
     302           4 :     req.key.reset(BuildKey(node->name()));
     303             : 
     304           4 :     boost::uuids::uuid dev_uuid = boost::uuids::nil_uuid();
     305             :     // Find link with physical-router adjacency
     306           4 :     IFMapNode *adj_node = NULL;
     307           4 :     adj_node = agent()->config_manager()->FindAdjacentIFMapNode(node,
     308             :                                                             "physical-router");
     309           4 :     if (adj_node) {
     310             :         autogen::PhysicalRouter *router =
     311           3 :             static_cast<autogen::PhysicalRouter *>(adj_node->GetObject());
     312           3 :         autogen::IdPermsType id_perms = router->id_perms();
     313           3 :         CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
     314             :                    dev_uuid);
     315           3 :     }
     316           4 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     317           8 :     req.data.reset(new PhysicalInterfaceData(agent(), node,
     318           4 :                                              agent()->fabric_vrf_name(),
     319             :                                              PhysicalInterface::CONFIG,
     320             :                                              PhysicalInterface::ETHERNET,
     321             :                                              false, dev_uuid,
     322           4 :                                              port->display_name(),
     323           4 :                                              Ip4Address(0),
     324           4 :                                              Interface::TRANSPORT_ETHERNET));
     325           4 :     pi_ifnode_to_req_++;
     326           4 :     Enqueue(&req);
     327           4 :     return false;
     328           4 : }
     329             : 
     330             : /////////////////////////////////////////////////////////////////////////////
     331             : // Utility methods
     332             : /////////////////////////////////////////////////////////////////////////////
     333             : // Enqueue DBRequest to create a Host Interface
     334           0 : void PhysicalInterface::CreateReq(InterfaceTable *table, const string &ifname,
     335             :                                   const string &vrf_name, SubType subtype,
     336             :                                   EncapType encap, bool no_arp,
     337             :                                   const boost::uuids::uuid &device_uuid,
     338             :                                   const Ip4Address &ip,
     339             :                                   Interface::Transport transport) {
     340           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     341           0 :     req.key.reset(new PhysicalInterfaceKey(ifname));
     342           0 :     req.data.reset(new PhysicalInterfaceData(NULL, NULL, vrf_name, subtype,
     343             :                                              encap, no_arp, device_uuid,
     344           0 :                                              ifname, ip, transport));
     345           0 :     table->Enqueue(&req);
     346           0 : }
     347             : 
     348           2 : void PhysicalInterface::Create(InterfaceTable *table, const string &ifname,
     349             :                                const string &vrf_name, SubType subtype,
     350             :                                EncapType encap, bool no_arp,
     351             :                                const boost::uuids::uuid &device_uuid,
     352             :                                const Ip4Address &ip,
     353             :                                Interface::Transport transport) {
     354           2 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     355           2 :     req.key.reset(new PhysicalInterfaceKey(ifname));
     356           2 :     req.data.reset(new PhysicalInterfaceData(NULL, NULL, vrf_name, subtype,
     357             :                                              encap, no_arp, device_uuid,
     358           2 :                                              ifname, ip, transport));
     359           2 :     table->Process(req);
     360           2 : }
     361             : 
     362             : // Enqueue DBRequest to delete a Host Interface
     363           0 : void PhysicalInterface::DeleteReq(InterfaceTable *table, const string &ifname) {
     364           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
     365           0 :     req.key.reset(new PhysicalInterfaceKey(ifname));
     366           0 :     req.data.reset(NULL);
     367           0 :     table->Enqueue(&req);
     368           0 : }
     369             : 
     370           0 : void PhysicalInterface::Delete(InterfaceTable *table, const string &ifname) {
     371           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
     372           0 :     req.key.reset(new PhysicalInterfaceKey(ifname));
     373           0 :     req.data.reset(NULL);
     374           0 :     table->Process(req);
     375           0 : }

Generated by: LCOV version 1.14