1 #include "rtnetlink.hpp"
2
3 #include <linux/netlink.h>
4 #include <linux/rtnetlink.h>
5
6 #include <stdplus/raw.hpp>
7
8 #include <gtest/gtest.h>
9
10 namespace phosphor::network::netlink
11 {
12
13 using stdplus::operator""_sub;
14 using stdplus::operator""_ip;
15
TEST(IntfFromRtm,SmallMsg)16 TEST(IntfFromRtm, SmallMsg)
17 {
18 EXPECT_THROW(intfFromRtm("1"), std::runtime_error);
19 }
20
TEST(IntfFromRtm,NoAttrs)21 TEST(IntfFromRtm, NoAttrs)
22 {
23 struct
24 {
25 ifinfomsg hdr __attribute__((aligned(NLMSG_ALIGNTO)));
26 } msg;
27 msg.hdr.ifi_type = 3;
28 msg.hdr.ifi_index = 1;
29 msg.hdr.ifi_flags = 2;
30 EXPECT_EQ(intfFromRtm(stdplus::raw::asView<char>(msg)),
31 (InterfaceInfo{.type = 3, .idx = 1, .flags = 2}));
32 }
33
TEST(IntfFromRtm,AllAttrs)34 TEST(IntfFromRtm, AllAttrs)
35 {
36 struct
37 {
38 ifinfomsg hdr __attribute__((aligned(NLMSG_ALIGNTO)));
39 rtattr addr_hdr __attribute__((aligned((RTA_ALIGNTO))));
40 char addr[6]
41 __attribute__((aligned((RTA_ALIGNTO)))) = {0, 1, 2, 3, 4, 5};
42 rtattr name_hdr __attribute__((aligned((RTA_ALIGNTO))));
43 char name[5] __attribute__((aligned((RTA_ALIGNTO)))) = "eth0";
44 rtattr mtu_hdr __attribute__((aligned((RTA_ALIGNTO))));
45 unsigned mtu __attribute__((aligned((RTA_ALIGNTO)))) = 50;
46 } msg;
47 msg.hdr.ifi_type = 4;
48 msg.hdr.ifi_index = 1;
49 msg.hdr.ifi_flags = 2;
50 msg.addr_hdr.rta_type = IFLA_ADDRESS;
51 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr));
52 msg.name_hdr.rta_type = IFLA_IFNAME;
53 msg.name_hdr.rta_len = RTA_LENGTH(sizeof(msg.name));
54 msg.mtu_hdr.rta_type = IFLA_MTU;
55 msg.mtu_hdr.rta_len = RTA_LENGTH(sizeof(msg.mtu));
56
57 auto info = intfFromRtm(stdplus::raw::asView<char>(msg));
58 auto expected = InterfaceInfo{.type = 4,
59 .idx = 1,
60 .flags = 2,
61 .name = "eth0",
62 .mac = ether_addr{0, 1, 2, 3, 4, 5},
63 .mtu = 50};
64 EXPECT_EQ(info, expected);
65 }
66
TEST(AddrFromRtm,MissingAddr)67 TEST(AddrFromRtm, MissingAddr)
68 {
69 struct
70 {
71 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa = {};
72 } msg;
73 EXPECT_THROW(addrFromRtm(stdplus::raw::asView<char>(msg)),
74 std::runtime_error);
75 }
76
TEST(AddrFromRtm,Regular)77 TEST(AddrFromRtm, Regular)
78 {
79 struct
80 {
81 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa;
82 alignas(NLMSG_ALIGNTO) rtattr addr_hdr;
83 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20};
84 } msg;
85 msg.ifa.ifa_family = AF_INET;
86 msg.ifa.ifa_prefixlen = 28;
87 msg.ifa.ifa_flags = 4;
88 msg.ifa.ifa_scope = 3;
89 msg.ifa.ifa_index = 10;
90 msg.addr_hdr.rta_type = IFA_ADDRESS;
91 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr));
92
93 auto ret = addrFromRtm(stdplus::raw::asView<char>(msg));
94 EXPECT_EQ(msg.ifa.ifa_flags, ret.flags);
95 EXPECT_EQ(msg.ifa.ifa_scope, ret.scope);
96 EXPECT_EQ(msg.ifa.ifa_index, ret.ifidx);
97 EXPECT_EQ("192.168.1.20/28"_sub, ret.ifaddr);
98 }
99
TEST(AddrFromRtm,ExtraFlags)100 TEST(AddrFromRtm, ExtraFlags)
101 {
102 struct
103 {
104 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa = {};
105 alignas(NLMSG_ALIGNTO) rtattr flags_hdr;
106 alignas(NLMSG_ALIGNTO) uint32_t flags = 0xff00ff00;
107 alignas(NLMSG_ALIGNTO) rtattr addr_hdr;
108 alignas(NLMSG_ALIGNTO) uint8_t addr[16] = {};
109 } msg;
110 msg.ifa.ifa_family = AF_INET6;
111 msg.flags_hdr.rta_type = IFA_FLAGS;
112 msg.flags_hdr.rta_len = RTA_LENGTH(sizeof(msg.flags));
113 msg.addr_hdr.rta_type = IFA_ADDRESS;
114 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr));
115
116 auto ret = addrFromRtm(stdplus::raw::asView<char>(msg));
117 EXPECT_EQ(0xff00ff00, ret.flags);
118 }
119
TEST(NeighFromRtm,MissingAddr)120 TEST(NeighFromRtm, MissingAddr)
121 {
122 struct
123 {
124 alignas(NLMSG_ALIGNTO) ndmsg ndm = {};
125 } msg;
126
127 EXPECT_EQ((NeighborInfo{}), neighFromRtm(stdplus::raw::asView<char>(msg)));
128 }
129
TEST(NeighFromRtm,NoMac)130 TEST(NeighFromRtm, NoMac)
131 {
132 struct
133 {
134 alignas(NLMSG_ALIGNTO) ndmsg ndm;
135 alignas(NLMSG_ALIGNTO) rtattr addr_hdr;
136 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20};
137 } msg;
138 msg.ndm.ndm_family = AF_INET;
139 msg.ndm.ndm_state = 4;
140 msg.addr_hdr.rta_type = NDA_DST;
141 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr));
142
143 auto ret = neighFromRtm(stdplus::raw::asView<char>(msg));
144 EXPECT_EQ(msg.ndm.ndm_state, ret.state);
145 EXPECT_EQ("192.168.1.20"_ip, ret.addr);
146 EXPECT_FALSE(ret.mac);
147 }
148
TEST(NeighFromRtm,Full)149 TEST(NeighFromRtm, Full)
150 {
151 struct
152 {
153 alignas(NLMSG_ALIGNTO) ndmsg ndm;
154 alignas(NLMSG_ALIGNTO) rtattr addr_hdr;
155 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20};
156 alignas(NLMSG_ALIGNTO) rtattr mac_hdr;
157 alignas(NLMSG_ALIGNTO) uint8_t mac[6] = {1, 2, 3, 4, 5, 6};
158 } msg;
159 msg.ndm.ndm_family = AF_INET;
160 msg.addr_hdr.rta_type = NDA_DST;
161 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr));
162 msg.mac_hdr.rta_type = NDA_LLADDR;
163 msg.mac_hdr.rta_len = RTA_LENGTH(sizeof(msg.mac));
164
165 auto ret = neighFromRtm(stdplus::raw::asView<char>(msg));
166 EXPECT_EQ("192.168.1.20"_ip, ret.addr);
167 EXPECT_EQ((ether_addr{1, 2, 3, 4, 5, 6}), ret.mac);
168 }
169
170 } // namespace phosphor::network::netlink
171