1a7344c3aSWilliam A. Kennington III #include "rtnetlink.hpp" 2a7344c3aSWilliam A. Kennington III 3a7344c3aSWilliam A. Kennington III #include "netlink.hpp" 46a92363eSWilliam A. Kennington III #include "util.hpp" 5a7344c3aSWilliam A. Kennington III 6a7344c3aSWilliam A. Kennington III #include <linux/rtnetlink.h> 7a7344c3aSWilliam A. Kennington III 8a7344c3aSWilliam A. Kennington III namespace phosphor::network::netlink 9a7344c3aSWilliam A. Kennington III { 10a7344c3aSWilliam A. Kennington III 111aeacc90SWilliam A. Kennington III using std::literals::string_view_literals::operator""sv; 121aeacc90SWilliam A. Kennington III 131aeacc90SWilliam A. Kennington III static void parseVlanInfo(InterfaceInfo& info, std::string_view msg) 141aeacc90SWilliam A. Kennington III { 151aeacc90SWilliam A. Kennington III if (msg.data() == nullptr) 161aeacc90SWilliam A. Kennington III { 171aeacc90SWilliam A. Kennington III throw std::runtime_error("Missing VLAN data"); 181aeacc90SWilliam A. Kennington III } 191aeacc90SWilliam A. Kennington III while (!msg.empty()) 201aeacc90SWilliam A. Kennington III { 211aeacc90SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg); 221aeacc90SWilliam A. Kennington III switch (hdr.rta_type) 231aeacc90SWilliam A. Kennington III { 241aeacc90SWilliam A. Kennington III case IFLA_VLAN_ID: 251aeacc90SWilliam A. Kennington III info.vlan_id.emplace(stdplus::raw::copyFrom<uint16_t>(data)); 261aeacc90SWilliam A. Kennington III break; 271aeacc90SWilliam A. Kennington III } 281aeacc90SWilliam A. Kennington III } 291aeacc90SWilliam A. Kennington III } 301aeacc90SWilliam A. Kennington III 311aeacc90SWilliam A. Kennington III static void parseLinkInfo(InterfaceInfo& info, std::string_view msg) 321aeacc90SWilliam A. Kennington III { 331aeacc90SWilliam A. Kennington III std::string_view submsg; 341aeacc90SWilliam A. Kennington III while (!msg.empty()) 351aeacc90SWilliam A. Kennington III { 361aeacc90SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg); 371aeacc90SWilliam A. Kennington III switch (hdr.rta_type) 381aeacc90SWilliam A. Kennington III { 391aeacc90SWilliam A. Kennington III case IFLA_INFO_KIND: 401aeacc90SWilliam A. Kennington III data.remove_suffix(1); 411aeacc90SWilliam A. Kennington III info.kind.emplace(data); 421aeacc90SWilliam A. Kennington III break; 431aeacc90SWilliam A. Kennington III case IFLA_INFO_DATA: 441aeacc90SWilliam A. Kennington III submsg = data; 451aeacc90SWilliam A. Kennington III break; 461aeacc90SWilliam A. Kennington III } 471aeacc90SWilliam A. Kennington III } 481aeacc90SWilliam A. Kennington III if (info.kind == "vlan"sv) 491aeacc90SWilliam A. Kennington III { 501aeacc90SWilliam A. Kennington III parseVlanInfo(info, submsg); 511aeacc90SWilliam A. Kennington III } 521aeacc90SWilliam A. Kennington III } 531aeacc90SWilliam A. Kennington III 541aeacc90SWilliam A. Kennington III InterfaceInfo intfFromRtm(std::string_view msg) 551aeacc90SWilliam A. Kennington III { 561aeacc90SWilliam A. Kennington III const auto& ifinfo = netlink::extractRtData<ifinfomsg>(msg); 571aeacc90SWilliam A. Kennington III InterfaceInfo ret; 58*9c441fd4SWilliam A. Kennington III ret.type = ifinfo.ifi_type; 591aeacc90SWilliam A. Kennington III ret.idx = ifinfo.ifi_index; 60*9c441fd4SWilliam A. Kennington III ret.flags = ifinfo.ifi_flags; 611aeacc90SWilliam A. Kennington III while (!msg.empty()) 621aeacc90SWilliam A. Kennington III { 631aeacc90SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg); 641aeacc90SWilliam A. Kennington III switch (hdr.rta_type) 651aeacc90SWilliam A. Kennington III { 661aeacc90SWilliam A. Kennington III case IFLA_IFNAME: 671aeacc90SWilliam A. Kennington III ret.name.emplace(data.begin(), data.end() - 1); 681aeacc90SWilliam A. Kennington III break; 691aeacc90SWilliam A. Kennington III case IFLA_ADDRESS: 701aeacc90SWilliam A. Kennington III if (data.size() == sizeof(ether_addr)) 711aeacc90SWilliam A. Kennington III { 721aeacc90SWilliam A. Kennington III ret.mac.emplace(stdplus::raw::copyFrom<ether_addr>(data)); 731aeacc90SWilliam A. Kennington III } 741aeacc90SWilliam A. Kennington III break; 751aeacc90SWilliam A. Kennington III case IFLA_MTU: 761aeacc90SWilliam A. Kennington III ret.mtu.emplace(stdplus::raw::copyFrom<unsigned>(data)); 771aeacc90SWilliam A. Kennington III break; 781aeacc90SWilliam A. Kennington III case IFLA_LINK: 791aeacc90SWilliam A. Kennington III ret.parent_idx.emplace(stdplus::raw::copyFrom<unsigned>(data)); 801aeacc90SWilliam A. Kennington III break; 811aeacc90SWilliam A. Kennington III case IFLA_LINKINFO: 821aeacc90SWilliam A. Kennington III parseLinkInfo(ret, data); 831aeacc90SWilliam A. Kennington III break; 841aeacc90SWilliam A. Kennington III } 851aeacc90SWilliam A. Kennington III } 861aeacc90SWilliam A. Kennington III return ret; 871aeacc90SWilliam A. Kennington III } 881aeacc90SWilliam A. Kennington III 89a7344c3aSWilliam A. Kennington III template <typename Addr> 90a7344c3aSWilliam A. Kennington III static std::optional<std::tuple<unsigned, InAddrAny>> 91a7344c3aSWilliam A. Kennington III parse(std::string_view msg) 92a7344c3aSWilliam A. Kennington III { 93a7344c3aSWilliam A. Kennington III std::optional<unsigned> ifIdx; 94a7344c3aSWilliam A. Kennington III std::optional<InAddrAny> gw; 95a7344c3aSWilliam A. Kennington III while (!msg.empty()) 96a7344c3aSWilliam A. Kennington III { 97a7344c3aSWilliam A. Kennington III auto [hdr, data] = extractRtAttr(msg); 98a7344c3aSWilliam A. Kennington III switch (hdr.rta_type) 99a7344c3aSWilliam A. Kennington III { 100a7344c3aSWilliam A. Kennington III case RTA_OIF: 1016a92363eSWilliam A. Kennington III ifIdx.emplace(stdplus::raw::copyFromStrict<int>(data)); 102a7344c3aSWilliam A. Kennington III break; 103a7344c3aSWilliam A. Kennington III case RTA_GATEWAY: 1046a92363eSWilliam A. Kennington III gw.emplace(stdplus::raw::copyFromStrict<Addr>(data)); 105a7344c3aSWilliam A. Kennington III break; 106a7344c3aSWilliam A. Kennington III } 107a7344c3aSWilliam A. Kennington III } 108a7344c3aSWilliam A. Kennington III if (ifIdx && gw) 109a7344c3aSWilliam A. Kennington III { 110a7344c3aSWilliam A. Kennington III return std::make_tuple(*ifIdx, *gw); 111a7344c3aSWilliam A. Kennington III } 112a7344c3aSWilliam A. Kennington III return std::nullopt; 113a7344c3aSWilliam A. Kennington III } 114a7344c3aSWilliam A. Kennington III 115a7344c3aSWilliam A. Kennington III std::optional<std::tuple<unsigned, InAddrAny>> 116a7344c3aSWilliam A. Kennington III gatewayFromRtm(std::string_view msg) 117a7344c3aSWilliam A. Kennington III { 118a7344c3aSWilliam A. Kennington III const auto& rtm = extractRtData<rtmsg>(msg); 119a7344c3aSWilliam A. Kennington III if (rtm.rtm_table != RT_TABLE_MAIN || rtm.rtm_dst_len != 0) 120a7344c3aSWilliam A. Kennington III { 121a7344c3aSWilliam A. Kennington III return std::nullopt; 122a7344c3aSWilliam A. Kennington III } 123a7344c3aSWilliam A. Kennington III switch (rtm.rtm_family) 124a7344c3aSWilliam A. Kennington III { 125a7344c3aSWilliam A. Kennington III case AF_INET: 126a7344c3aSWilliam A. Kennington III return parse<in_addr>(msg); 127a7344c3aSWilliam A. Kennington III case AF_INET6: 128a7344c3aSWilliam A. Kennington III return parse<in6_addr>(msg); 129a7344c3aSWilliam A. Kennington III } 130a7344c3aSWilliam A. Kennington III return std::nullopt; 131a7344c3aSWilliam A. Kennington III } 132a7344c3aSWilliam A. Kennington III 1336a92363eSWilliam A. Kennington III AddressInfo addrFromRtm(std::string_view msg) 1346a92363eSWilliam A. Kennington III { 1356a92363eSWilliam A. Kennington III const auto& ifa = extractRtData<ifaddrmsg>(msg); 1366a92363eSWilliam A. Kennington III 1376a92363eSWilliam A. Kennington III AddressInfo ret; 1386a92363eSWilliam A. Kennington III ret.ifidx = ifa.ifa_index; 1396a92363eSWilliam A. Kennington III ret.flags = ifa.ifa_flags; 1406a92363eSWilliam A. Kennington III ret.scope = ifa.ifa_scope; 1416a92363eSWilliam A. Kennington III std::optional<InAddrAny> addr; 1426a92363eSWilliam A. Kennington III while (!msg.empty()) 1436a92363eSWilliam A. Kennington III { 1446a92363eSWilliam A. Kennington III auto [hdr, data] = extractRtAttr(msg); 1456a92363eSWilliam A. Kennington III if (hdr.rta_type == IFA_ADDRESS) 1466a92363eSWilliam A. Kennington III { 1476a92363eSWilliam A. Kennington III addr.emplace(addrFromBuf(ifa.ifa_family, data)); 1486a92363eSWilliam A. Kennington III } 1496a92363eSWilliam A. Kennington III else if (hdr.rta_type == IFA_FLAGS) 1506a92363eSWilliam A. Kennington III { 1516a92363eSWilliam A. Kennington III ret.flags = stdplus::raw::copyFromStrict<uint32_t>(data); 1526a92363eSWilliam A. Kennington III } 1536a92363eSWilliam A. Kennington III } 1546a92363eSWilliam A. Kennington III if (!addr) 1556a92363eSWilliam A. Kennington III { 1566a92363eSWilliam A. Kennington III throw std::runtime_error("Missing address"); 1576a92363eSWilliam A. Kennington III } 1586a92363eSWilliam A. Kennington III ret.ifaddr = {*addr, ifa.ifa_prefixlen}; 1596a92363eSWilliam A. Kennington III return ret; 1606a92363eSWilliam A. Kennington III } 1616a92363eSWilliam A. Kennington III 162a8426902SWilliam A. Kennington III NeighborInfo neighFromRtm(std::string_view msg) 163a8426902SWilliam A. Kennington III { 164a8426902SWilliam A. Kennington III const auto& ndm = netlink::extractRtData<ndmsg>(msg); 165a8426902SWilliam A. Kennington III 166a8426902SWilliam A. Kennington III NeighborInfo ret; 167a8426902SWilliam A. Kennington III ret.ifidx = ndm.ndm_ifindex; 168a8426902SWilliam A. Kennington III ret.state = ndm.ndm_state; 169a8426902SWilliam A. Kennington III while (!msg.empty()) 170a8426902SWilliam A. Kennington III { 171a8426902SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg); 172a8426902SWilliam A. Kennington III if (hdr.rta_type == NDA_LLADDR) 173a8426902SWilliam A. Kennington III { 174a8426902SWilliam A. Kennington III ret.mac = stdplus::raw::copyFrom<ether_addr>(data); 175a8426902SWilliam A. Kennington III } 176a8426902SWilliam A. Kennington III else if (hdr.rta_type == NDA_DST) 177a8426902SWilliam A. Kennington III { 178a8426902SWilliam A. Kennington III ret.addr = addrFromBuf(ndm.ndm_family, data); 179a8426902SWilliam A. Kennington III } 180a8426902SWilliam A. Kennington III } 181a8426902SWilliam A. Kennington III return ret; 182a8426902SWilliam A. Kennington III } 183a8426902SWilliam A. Kennington III 184a7344c3aSWilliam A. Kennington III } // namespace phosphor::network::netlink 185