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 16 TEST(IntfFromRtm, SmallMsg) 17 { 18 EXPECT_THROW(intfFromRtm("1"), std::runtime_error); 19 } 20 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 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{ 59 .type = 4, 60 .idx = 1, 61 .flags = 2, 62 .name = "eth0", 63 .mac = ether_addr{0, 1, 2, 3, 4, 5}, 64 .mtu = 50}; 65 EXPECT_EQ(info, expected); 66 } 67 68 TEST(AddrFromRtm, MissingAddr) 69 { 70 struct 71 { 72 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa = {}; 73 } msg; 74 EXPECT_THROW(addrFromRtm(stdplus::raw::asView<char>(msg)), 75 std::runtime_error); 76 } 77 78 TEST(AddrFromRtm, Regular) 79 { 80 struct 81 { 82 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa; 83 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 84 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20}; 85 } msg; 86 msg.ifa.ifa_family = AF_INET; 87 msg.ifa.ifa_prefixlen = 28; 88 msg.ifa.ifa_flags = 4; 89 msg.ifa.ifa_scope = 3; 90 msg.ifa.ifa_index = 10; 91 msg.addr_hdr.rta_type = IFA_ADDRESS; 92 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 93 94 auto ret = addrFromRtm(stdplus::raw::asView<char>(msg)); 95 EXPECT_EQ(msg.ifa.ifa_flags, ret.flags); 96 EXPECT_EQ(msg.ifa.ifa_scope, ret.scope); 97 EXPECT_EQ(msg.ifa.ifa_index, ret.ifidx); 98 EXPECT_EQ("192.168.1.20/28"_sub, ret.ifaddr); 99 } 100 101 TEST(AddrFromRtm, ExtraFlags) 102 { 103 struct 104 { 105 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa = {}; 106 alignas(NLMSG_ALIGNTO) rtattr flags_hdr; 107 alignas(NLMSG_ALIGNTO) uint32_t flags = 0xff00ff00; 108 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 109 alignas(NLMSG_ALIGNTO) uint8_t addr[16] = {}; 110 } msg; 111 msg.ifa.ifa_family = AF_INET6; 112 msg.flags_hdr.rta_type = IFA_FLAGS; 113 msg.flags_hdr.rta_len = RTA_LENGTH(sizeof(msg.flags)); 114 msg.addr_hdr.rta_type = IFA_ADDRESS; 115 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 116 117 auto ret = addrFromRtm(stdplus::raw::asView<char>(msg)); 118 EXPECT_EQ(0xff00ff00, ret.flags); 119 } 120 121 TEST(NeighFromRtm, MissingAddr) 122 { 123 struct 124 { 125 alignas(NLMSG_ALIGNTO) ndmsg ndm = {}; 126 } msg; 127 128 EXPECT_EQ((NeighborInfo{}), neighFromRtm(stdplus::raw::asView<char>(msg))); 129 } 130 131 TEST(NeighFromRtm, NoMac) 132 { 133 struct 134 { 135 alignas(NLMSG_ALIGNTO) ndmsg ndm; 136 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 137 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20}; 138 } msg; 139 msg.ndm.ndm_family = AF_INET; 140 msg.ndm.ndm_state = 4; 141 msg.addr_hdr.rta_type = NDA_DST; 142 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 143 144 auto ret = neighFromRtm(stdplus::raw::asView<char>(msg)); 145 EXPECT_EQ(msg.ndm.ndm_state, ret.state); 146 EXPECT_EQ("192.168.1.20"_ip, ret.addr); 147 EXPECT_FALSE(ret.mac); 148 } 149 150 TEST(NeighFromRtm, Full) 151 { 152 struct 153 { 154 alignas(NLMSG_ALIGNTO) ndmsg ndm; 155 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 156 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20}; 157 alignas(NLMSG_ALIGNTO) rtattr mac_hdr; 158 alignas(NLMSG_ALIGNTO) uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; 159 } msg; 160 msg.ndm.ndm_family = AF_INET; 161 msg.addr_hdr.rta_type = NDA_DST; 162 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 163 msg.mac_hdr.rta_type = NDA_LLADDR; 164 msg.mac_hdr.rta_len = RTA_LENGTH(sizeof(msg.mac)); 165 166 auto ret = neighFromRtm(stdplus::raw::asView<char>(msg)); 167 EXPECT_EQ("192.168.1.20"_ip, ret.addr); 168 EXPECT_EQ((ether_addr{1, 2, 3, 4, 5, 6}), ret.mac); 169 } 170 171 } // namespace phosphor::network::netlink 172