blob: c1f8facd13ebe092684927cc928a3f1c47bd4f14 [file] [log] [blame]
William A. Kennington III08505792019-01-30 16:00:04 -08001#include "config.h"
2
3#include "neighbor.hpp"
4
5#include "ethernet_interface.hpp"
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07006#include "netlink.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08007#include "util.hpp"
8
9#include <linux/neighbour.h>
10#include <linux/netlink.h>
11#include <linux/rtnetlink.h>
12#include <net/if.h>
13#include <sys/socket.h>
14#include <sys/types.h>
15
William A. Kennington III08505792019-01-30 16:00:04 -080016#include <stdexcept>
William A. Kennington III12beaad2020-06-13 19:30:41 -070017#include <stdplus/raw.hpp>
William A. Kennington III08505792019-01-30 16:00:04 -080018#include <string_view>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070019#include <utility>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070020#include <vector>
William A. Kennington III08505792019-01-30 16:00:04 -080021
22namespace phosphor
23{
24namespace network
25{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070026namespace detail
William A. Kennington III08505792019-01-30 16:00:04 -080027{
William A. Kennington III08505792019-01-30 16:00:04 -080028
William A. Kennington IIId7946a72019-04-19 14:24:09 -070029void parseNeighbor(const NeighborFilter& filter, const nlmsghdr& hdr,
30 std::string_view msg, std::vector<NeighborInfo>& neighbors)
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070031{
32 if (hdr.nlmsg_type != RTM_NEWNEIGH)
33 {
34 throw std::runtime_error("Not a neighbor msg");
35 }
William A. Kennington III12beaad2020-06-13 19:30:41 -070036 auto ndm = stdplus::raw::extract<ndmsg>(msg);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070037
William A. Kennington IIId7946a72019-04-19 14:24:09 -070038 // Filter out neighbors we don't care about
39 unsigned ifindex = ndm.ndm_ifindex;
40 if (filter.interface != 0 && filter.interface != ifindex)
William A. Kennington III08505792019-01-30 16:00:04 -080041 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -070042 return;
William A. Kennington III08505792019-01-30 16:00:04 -080043 }
William A. Kennington IIId7946a72019-04-19 14:24:09 -070044 if ((ndm.ndm_state & filter.state) == 0)
45 {
46 return;
47 }
48
49 // Build the neighbor info for our valid neighbor
50 NeighborInfo neighbor;
51 neighbor.interface = ifindex;
52 neighbor.state = ndm.ndm_state;
William A. Kennington III08505792019-01-30 16:00:04 -080053 bool set_addr = false;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070054 while (!msg.empty())
William A. Kennington III08505792019-01-30 16:00:04 -080055 {
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070056 auto [hdr, data] = netlink::extractRtAttr(msg);
William A. Kennington III08505792019-01-30 16:00:04 -080057 if (hdr.rta_type == NDA_LLADDR)
58 {
William A. Kennington III12beaad2020-06-13 19:30:41 -070059 neighbor.mac = stdplus::raw::copyFrom<ether_addr>(data);
William A. Kennington III08505792019-01-30 16:00:04 -080060 }
61 else if (hdr.rta_type == NDA_DST)
62 {
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070063 neighbor.address = addrFromBuf(ndm.ndm_family, data);
William A. Kennington III08505792019-01-30 16:00:04 -080064 set_addr = true;
65 }
William A. Kennington III08505792019-01-30 16:00:04 -080066 }
67 if (!set_addr)
68 {
69 throw std::runtime_error("Missing address");
70 }
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070071 neighbors.push_back(std::move(neighbor));
William A. Kennington III08505792019-01-30 16:00:04 -080072}
73
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070074} // namespace detail
William A. Kennington III08505792019-01-30 16:00:04 -080075
William A. Kennington IIId7946a72019-04-19 14:24:09 -070076std::vector<NeighborInfo> getCurrentNeighbors(const NeighborFilter& filter)
William A. Kennington III08505792019-01-30 16:00:04 -080077{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070078 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070079 auto cb = [&filter, &neighbors](const nlmsghdr& hdr, std::string_view msg) {
80 detail::parseNeighbor(filter, hdr, msg, neighbors);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070081 };
William A. Kennington IIId7946a72019-04-19 14:24:09 -070082 ndmsg msg{};
83 msg.ndm_ifindex = filter.interface;
84 netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070085 return neighbors;
William A. Kennington III08505792019-01-30 16:00:04 -080086}
87
88Neighbor::Neighbor(sdbusplus::bus::bus& bus, const char* objPath,
89 EthernetInterface& parent, const std::string& ipAddress,
90 const std::string& macAddress, State state) :
Patrick Williams166b9592022-03-30 16:09:16 -050091 NeighborObj(bus, objPath, NeighborObj::action::defer_emit),
William A. Kennington III08505792019-01-30 16:00:04 -080092 parent(parent)
93{
Patrick Williams6aef7692021-05-01 06:39:41 -050094 this->ipAddress(ipAddress);
95 this->macAddress(macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -080096 this->state(state);
97
98 // Emit deferred signal.
99 emit_object_added();
100}
101
102void Neighbor::delete_()
103{
Patrick Williams6aef7692021-05-01 06:39:41 -0500104 parent.deleteStaticNeighborObject(ipAddress());
William A. Kennington III08505792019-01-30 16:00:04 -0800105}
106
107} // namespace network
108} // namespace phosphor