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