| @@ -35,7 +35,8 @@ · 34 unmodified lines |
| 35 | #include <net/xfrm.h> | 35 | #include <net/xfrm.h> |
| 36 | #include <linux/netpoll.h> | 36 | #include <linux/netpoll.h> |
| 37 | | 37 | |
| 38 | #define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) | 38 | #define MACVLAN_HASH_BITS 8 |
| | 39 | #define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS) |
| 39 | #define MACVLAN_BC_QUEUE_LEN 1000 | 40 | #define MACVLAN_BC_QUEUE_LEN 1000 |
| 40 | | 41 | |
| 41 | struct macvlan_port { | 42 | struct macvlan_port { |
| @@ -47,6 +48,14 @@ struct macvlan_port { · 5 unmodified lines |
| 47 | struct work_struct bc_work; | 48 | struct work_struct bc_work; |
| 48 | bool passthru; | 49 | bool passthru; |
| 49 | int count; | 50 | int count; |
| | 51 | struct hlist_head vlan_source_hash[MACVLAN_HASH_SIZE]; |
| | 52 | }; |
| | 53 | |
| | 54 | struct macvlan_source_entry { |
| | 55 | struct hlist_node hlist; |
| | 56 | struct macvlan_dev *vlan; |
| | 57 | unsigned char addr[6+2] __aligned(sizeof(u16)); |
| | 58 | struct rcu_head rcu; |
| 50 | }; | 59 | }; |
| 51 | | 60 | |
| 52 | struct macvlan_skb_cb { | 61 | struct macvlan_skb_cb { |
| @@ -57,6 +66,20 @@ struct macvlan_skb_cb { · 4 unmodified lines |
| 57 | | 66 | |
| 58 | static void macvlan_port_destroy(struct net_device *dev); | 67 | static void macvlan_port_destroy(struct net_device *dev); |
| 59 | | 68 | |
| | 69 | /* Hash Ethernet address */ |
| | 70 | static u32 macvlan_eth_hash(const unsigned char *addr) |
| | 71 | { |
| | 72 | u64 value = get_unaligned((u64 *)addr); |
| | 73 | |
| | 74 | /* only want 6 bytes */ |
| | 75 | #ifdef __BIG_ENDIAN |
| | 76 | value >>= 16; |
| | 77 | #else |
| | 78 | value <<= 16; |
| | 79 | #endif |
| | 80 | return hash_64(value, MACVLAN_HASH_BITS); |
| | 81 | } |
| | 82 | |
| 60 | static struct macvlan_port *macvlan_port_get_rcu(const struct net_device *dev) | 83 | static struct macvlan_port *macvlan_port_get_rcu(const struct net_device *dev) |
| 61 | { | 84 | { |
| 62 | return rcu_dereference(dev->rx_handler_data); | 85 | return rcu_dereference(dev->rx_handler_data); |
| @@ -73,20 +96,68 @@ static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, · 10 unmodified lines |
| 73 | const unsigned char *addr) | 96 | const unsigned char *addr) |
| 74 | { | 97 | { |
| 75 | struct macvlan_dev *vlan; | 98 | struct macvlan_dev *vlan; |
| | 99 | u32 idx = macvlan_eth_hash(addr); |
| 76 | | 100 | |
| 77 | hlist_for_each_entry_rcu(vlan, &port->vlan_hash[addr[5]], hlist) { | 101 | hlist_for_each_entry_rcu(vlan, &port->vlan_hash[idx], hlist) { |
| 78 | if (ether_addr_equal_64bits(vlan->dev->dev_addr, addr)) | 102 | if (ether_addr_equal_64bits(vlan->dev->dev_addr, addr)) |
| 79 | return vlan; | 103 | return vlan; |
| 80 | } | 104 | } |
| 81 | return NULL; | 105 | return NULL; |
| 82 | } | 106 | } |
| 83 | | 107 | |
| | 108 | static struct macvlan_source_entry *macvlan_hash_lookup_source( |
| | 109 | const struct macvlan_dev *vlan, |
| | 110 | const unsigned char *addr) |
| | 111 | { |
| | 112 | struct macvlan_source_entry *entry; |
| | 113 | u32 idx = macvlan_eth_hash(addr); |
| | 114 | struct hlist_head *h = &vlan->port->vlan_source_hash[idx]; |
| | 115 | |
| | 116 | hlist_for_each_entry_rcu(entry, h, hlist) { |
| | 117 | if (ether_addr_equal_64bits(entry->addr, addr) && |
| | 118 | entry->vlan == vlan) |
| | 119 | return entry; |
| | 120 | } |
| | 121 | return NULL; |
| | 122 | } |
| | 123 | |
| | 124 | static int macvlan_hash_add_source(struct macvlan_dev *vlan, |
| | 125 | const unsigned char *addr) |
| | 126 | { |
| | 127 | struct macvlan_port *port = vlan->port; |
| | 128 | struct macvlan_source_entry *entry; |
| | 129 | struct hlist_head *h; |
| | 130 | |
| | 131 | entry = macvlan_hash_lookup_source(vlan, addr); |
| | 132 | if (entry) |
| | 133 | return 0; |
| | 134 | |
| | 135 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
| | 136 | if (!entry) |
| | 137 | return -ENOMEM; |
| | 138 | |
| | 139 | ether_addr_copy(entry->addr, addr); |
| | 140 | entry->vlan = vlan; |
| | 141 | h = &port->vlan_source_hash[macvlan_eth_hash(addr)]; |
| | 142 | hlist_add_head_rcu(&entry->hlist, h); |
| | 143 | vlan->macaddr_count++; |
| | 144 | |
| | 145 | return 0; |
| | 146 | } |
| | 147 | |
| 84 | static void macvlan_hash_add(struct macvlan_dev *vlan) | 148 | static void macvlan_hash_add(struct macvlan_dev *vlan) |
| 85 | { | 149 | { |
| 86 | struct macvlan_port *port = vlan->port; | 150 | struct macvlan_port *port = vlan->port; |
| 87 | const unsigned char *addr = vlan->dev->dev_addr; | 151 | const unsigned char *addr = vlan->dev->dev_addr; |
| | 152 | u32 idx = macvlan_eth_hash(addr); |
| 88 | | 153 | |
| 89 | hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[addr[5]]); | 154 | hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[idx]); |
| | 155 | } |
| | 156 | |
| | 157 | static void macvlan_hash_del_source(struct macvlan_source_entry *entry) |
| | 158 | { |
| | 159 | hlist_del_rcu(&entry->hlist); |
| | 160 | kfree_rcu(entry, rcu); |
| 90 | } | 161 | } |
| 91 | | 162 | |
| 92 | static void macvlan_hash_del(struct macvlan_dev *vlan, bool sync) | 163 | static void macvlan_hash_del(struct macvlan_dev *vlan, bool sync) |
| @@ -267,6 +338,65 @@ err: · 174 unmodified lines |
| 267 | atomic_long_inc(&skb->dev->rx_dropped); | 338 | atomic_long_inc(&skb->dev->rx_dropped); |
| 268 | } | 339 | } |
| 269 | | 340 | |
| | 341 | static void macvlan_flush_sources(struct macvlan_port *port, |
| | 342 | struct macvlan_dev *vlan) |
| | 343 | { |
| | 344 | int i; |
| | 345 | |
| | 346 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) { |
| | 347 | struct hlist_node *h, *n; |
| | 348 | |
| | 349 | hlist_for_each_safe(h, n, &port->vlan_source_hash[i]) { |
| | 350 | struct macvlan_source_entry *entry; |
| | 351 | |
| | 352 | entry = hlist_entry(h, struct macvlan_source_entry, |
| | 353 | hlist); |
| | 354 | if (entry->vlan == vlan) |
| | 355 | macvlan_hash_del_source(entry); |
| | 356 | } |
| | 357 | } |
| | 358 | vlan->macaddr_count = 0; |
| | 359 | } |
| | 360 | |
| | 361 | static void macvlan_forward_source_one(struct sk_buff *skb, |
| | 362 | struct macvlan_dev *vlan) |
| | 363 | { |
| | 364 | struct sk_buff *nskb; |
| | 365 | struct net_device *dev; |
| | 366 | int len; |
| | 367 | int ret; |
| | 368 | |
| | 369 | dev = vlan->dev; |
| | 370 | if (unlikely(!(dev->flags & IFF_UP))) |
| | 371 | return; |
| | 372 | |
| | 373 | nskb = skb_clone(skb, GFP_ATOMIC); |
| | 374 | if (!nskb) |
| | 375 | return; |
| | 376 | |
| | 377 | len = nskb->len + ETH_HLEN; |
| | 378 | nskb->dev = dev; |
| | 379 | nskb->pkt_type = PACKET_HOST; |
| | 380 | |
| | 381 | ret = netif_rx(nskb); |
| | 382 | macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0); |
| | 383 | } |
| | 384 | |
| | 385 | static void macvlan_forward_source(struct sk_buff *skb, |
| | 386 | struct macvlan_port *port, |
| | 387 | const unsigned char *addr) |
| | 388 | { |
| | 389 | struct macvlan_source_entry *entry; |
| | 390 | u32 idx = macvlan_eth_hash(addr); |
| | 391 | struct hlist_head *h = &port->vlan_source_hash[idx]; |
| | 392 | |
| | 393 | hlist_for_each_entry_rcu(entry, h, hlist) { |
| | 394 | if (ether_addr_equal_64bits(entry->addr, addr)) |
| | 395 | if (entry->vlan->dev->flags & IFF_UP) |
| | 396 | macvlan_forward_source_one(skb, entry->vlan); |
| | 397 | } |
| | 398 | } |
| | 399 | |
| 270 | /* called under rcu_read_lock() from netif_receive_skb */ | 400 | /* called under rcu_read_lock() from netif_receive_skb */ |
| 271 | static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) | 401 | static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) |
| 272 | { | 402 | { |
| @@ -285,6 +415,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) · 12 unmodified lines |
| 285 | if (!skb) | 415 | if (!skb) |
| 286 | return RX_HANDLER_CONSUMED; | 416 | return RX_HANDLER_CONSUMED; |
| 287 | eth = eth_hdr(skb); | 417 | eth = eth_hdr(skb); |
| | 418 | macvlan_forward_source(skb, port, eth->h_source); |
| 288 | src = macvlan_hash_lookup(port, eth->h_source); | 419 | src = macvlan_hash_lookup(port, eth->h_source); |
| 289 | if (src && src->mode != MACVLAN_MODE_VEPA && | 420 | if (src && src->mode != MACVLAN_MODE_VEPA && |
| 290 | src->mode != MACVLAN_MODE_BRIDGE) { | 421 | src->mode != MACVLAN_MODE_BRIDGE) { |
| @@ -301,6 +432,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) · 10 unmodified lines |
| 301 | return RX_HANDLER_PASS; | 432 | return RX_HANDLER_PASS; |
| 302 | } | 433 | } |
| 303 | | 434 | |
| | 435 | macvlan_forward_source(skb, port, eth->h_source); |
| 304 | if (port->passthru) | 436 | if (port->passthru) |
| 305 | vlan = list_first_or_null_rcu(&port->vlans, | 437 | vlan = list_first_or_null_rcu(&port->vlans, |
| 306 | struct macvlan_dev, list); | 438 | struct macvlan_dev, list); |
| @@ -667,6 +799,7 @@ static void macvlan_uninit(struct net_device *dev) · 360 unmodified lines |
| 667 | | 799 | |
| 668 | free_percpu(vlan->pcpu_stats); | 800 | free_percpu(vlan->pcpu_stats); |
| 669 | | 801 | |
| | 802 | macvlan_flush_sources(port, vlan); |
| 670 | port->count -= 1; | 803 | port->count -= 1; |
| 671 | if (!port->count) | 804 | if (!port->count) |
| 672 | macvlan_port_destroy(port->dev); | 805 | macvlan_port_destroy(port->dev); |
| @@ -925,6 +1058,8 @@ static int macvlan_port_create(struct net_device *dev) · 252 unmodified lines |
| 925 | INIT_LIST_HEAD(&port->vlans); | 1058 | INIT_LIST_HEAD(&port->vlans); |
| 926 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) | 1059 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) |
| 927 | INIT_HLIST_HEAD(&port->vlan_hash[i]); | 1060 | INIT_HLIST_HEAD(&port->vlan_hash[i]); |
| | 1061 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) |
| | 1062 | INIT_HLIST_HEAD(&port->vlan_source_hash[i]); |
| 928 | | 1063 | |
| 929 | skb_queue_head_init(&port->bc_queue); | 1064 | skb_queue_head_init(&port->bc_queue); |
| 930 | INIT_WORK(&port->bc_work, macvlan_process_broadcast); | 1065 | INIT_WORK(&port->bc_work, macvlan_process_broadcast); |
| @@ -966,11 +1101,102 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) · 35 unmodified lines |
| 966 | case MACVLAN_MODE_VEPA: | 1101 | case MACVLAN_MODE_VEPA: |
| 967 | case MACVLAN_MODE_BRIDGE: | 1102 | case MACVLAN_MODE_BRIDGE: |
| 968 | case MACVLAN_MODE_PASSTHRU: | 1103 | case MACVLAN_MODE_PASSTHRU: |
| | 1104 | case MACVLAN_MODE_SOURCE: |
| | 1105 | break; |
| | 1106 | default: |
| | 1107 | return -EINVAL; |
| | 1108 | } |
| | 1109 | } |
| | 1110 | |
| | 1111 | if (data && data[IFLA_MACVLAN_MACADDR_MODE]) { |
| | 1112 | switch (nla_get_u32(data[IFLA_MACVLAN_MACADDR_MODE])) { |
| | 1113 | case MACVLAN_MACADDR_ADD: |
| | 1114 | case MACVLAN_MACADDR_DEL: |
| | 1115 | case MACVLAN_MACADDR_FLUSH: |
| | 1116 | case MACVLAN_MACADDR_SET: |
| 969 | break; | 1117 | break; |
| 970 | default: | 1118 | default: |
| 971 | return -EINVAL; | 1119 | return -EINVAL; |
| 972 | } | 1120 | } |
| 973 | } | 1121 | } |
| | 1122 | |
| | 1123 | if (data && data[IFLA_MACVLAN_MACADDR]) { |
| | 1124 | if (nla_len(data[IFLA_MACVLAN_MACADDR]) != ETH_ALEN) |
| | 1125 | return -EINVAL; |
| | 1126 | |
| | 1127 | if (!is_valid_ether_addr(nla_data(data[IFLA_MACVLAN_MACADDR]))) |
| | 1128 | return -EADDRNOTAVAIL; |
| | 1129 | } |
| | 1130 | |
| | 1131 | if (data && data[IFLA_MACVLAN_MACADDR_COUNT]) |
| | 1132 | return -EINVAL; |
| | 1133 | |
| | 1134 | return 0; |
| | 1135 | } |
| | 1136 | |
| | 1137 | /** |
| | 1138 | * reconfigure list of remote source mac address |
| | 1139 | * (only for macvlan devices in source mode) |
| | 1140 | * Note regarding alignment: all netlink data is aligned to 4 Byte, which |
| | 1141 | * suffices for both ether_addr_copy and ether_addr_equal_64bits usage. |
| | 1142 | */ |
| | 1143 | static int macvlan_changelink_sources(struct macvlan_dev *vlan, u32 mode, |
| | 1144 | struct nlattr *data[]) |
| | 1145 | { |
| | 1146 | char *addr = NULL; |
| | 1147 | int ret, rem, len; |
| | 1148 | struct nlattr *nla, *head; |
| | 1149 | struct macvlan_source_entry *entry; |
| | 1150 | |
| | 1151 | if (data[IFLA_MACVLAN_MACADDR]) |
| | 1152 | addr = nla_data(data[IFLA_MACVLAN_MACADDR]); |
| | 1153 | |
| | 1154 | if (mode == MACVLAN_MACADDR_ADD) { |
| | 1155 | if (!addr) |
| | 1156 | return -EINVAL; |
| | 1157 | |
| | 1158 | return macvlan_hash_add_source(vlan, addr); |
| | 1159 | |
| | 1160 | } else if (mode == MACVLAN_MACADDR_DEL) { |
| | 1161 | if (!addr) |
| | 1162 | return -EINVAL; |
| | 1163 | |
| | 1164 | entry = macvlan_hash_lookup_source(vlan, addr); |
| | 1165 | if (entry) { |
| | 1166 | macvlan_hash_del_source(entry); |
| | 1167 | vlan->macaddr_count--; |
| | 1168 | } |
| | 1169 | } else if (mode == MACVLAN_MACADDR_FLUSH) { |
| | 1170 | macvlan_flush_sources(vlan->port, vlan); |
| | 1171 | } else if (mode == MACVLAN_MACADDR_SET) { |
| | 1172 | macvlan_flush_sources(vlan->port, vlan); |
| | 1173 | |
| | 1174 | if (addr) { |
| | 1175 | ret = macvlan_hash_add_source(vlan, addr); |
| | 1176 | if (ret) |
| | 1177 | return ret; |
| | 1178 | } |
| | 1179 | |
| | 1180 | if (!data || !data[IFLA_MACVLAN_MACADDR_DATA]) |
| | 1181 | return 0; |
| | 1182 | |
| | 1183 | head = nla_data(data[IFLA_MACVLAN_MACADDR_DATA]); |
| | 1184 | len = nla_len(data[IFLA_MACVLAN_MACADDR_DATA]); |
| | 1185 | |
| | 1186 | nla_for_each_attr(nla, head, len, rem) { |
| | 1187 | if (nla_type(nla) != IFLA_MACVLAN_MACADDR || |
| | 1188 | nla_len(nla) != ETH_ALEN) |
| | 1189 | continue; |
| | 1190 | |
| | 1191 | addr = nla_data(nla); |
| | 1192 | ret = macvlan_hash_add_source(vlan, addr); |
| | 1193 | if (ret) |
| | 1194 | return ret; |
| | 1195 | } |
| | 1196 | } else { |
| | 1197 | return -EINVAL; |
| | 1198 | } |
| | 1199 | |
| 974 | return 0; | 1200 | return 0; |
| 975 | } | 1201 | } |
| 976 | | 1202 | |
| @@ -981,6 +1207,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, · 4 unmodified lines |
| 981 | struct macvlan_port *port; | 1207 | struct macvlan_port *port; |
| 982 | struct net_device *lowerdev; | 1208 | struct net_device *lowerdev; |
| 983 | int err; | 1209 | int err; |
| | 1210 | int macmode; |
| 984 | | 1211 | |
| 985 | if (!tb[IFLA_LINK]) | 1212 | if (!tb[IFLA_LINK]) |
| 986 | return -EINVAL; | 1213 | return -EINVAL; |
| @@ -1034,6 +1261,15 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, · 47 unmodified lines |
| 1034 | eth_hw_addr_inherit(dev, lowerdev); | 1261 | eth_hw_addr_inherit(dev, lowerdev); |
| 1035 | } | 1262 | } |
| 1036 | | 1263 | |
| | 1264 | if (data && data[IFLA_MACVLAN_MACADDR_MODE]) { |
| | 1265 | if (vlan->mode != MACVLAN_MODE_SOURCE) |
| | 1266 | return -EINVAL; |
| | 1267 | macmode = nla_get_u32(data[IFLA_MACVLAN_MACADDR_MODE]); |
| | 1268 | err = macvlan_changelink_sources(vlan, macmode, data); |
| | 1269 | if (err) |
| | 1270 | return err; |
| | 1271 | } |
| | 1272 | |
| 1037 | port->count += 1; | 1273 | port->count += 1; |
| 1038 | err = register_netdevice(dev); | 1274 | err = register_netdevice(dev); |
| 1039 | if (err < 0) | 1275 | if (err < 0) |
| @@ -1070,6 +1306,8 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head) · 30 unmodified lines |
| 1070 | { | 1306 | { |
| 1071 | struct macvlan_dev *vlan = netdev_priv(dev); | 1307 | struct macvlan_dev *vlan = netdev_priv(dev); |
| 1072 | | 1308 | |
| | 1309 | if (vlan->mode == MACVLAN_MODE_SOURCE) |
| | 1310 | macvlan_flush_sources(vlan->port, vlan); |
| 1073 | list_del_rcu(&vlan->list); | 1311 | list_del_rcu(&vlan->list); |
| 1074 | unregister_netdevice_queue(dev, head); | 1312 | unregister_netdevice_queue(dev, head); |
| 1075 | netdev_upper_dev_unlink(vlan->lowerdev, dev); | 1313 | netdev_upper_dev_unlink(vlan->lowerdev, dev); |
| @@ -1082,6 +1320,8 @@ static int macvlan_changelink(struct net_device *dev, · 6 unmodified lines |
| 1082 | struct macvlan_dev *vlan = netdev_priv(dev); | 1320 | struct macvlan_dev *vlan = netdev_priv(dev); |
| 1083 | enum macvlan_mode mode; | 1321 | enum macvlan_mode mode; |
| 1084 | bool set_mode = false; | 1322 | bool set_mode = false; |
| | 1323 | enum macvlan_macaddr_mode macmode; |
| | 1324 | int ret; |
| 1085 | | 1325 | |
| 1086 | /* Validate mode, but don't set yet: setting flags may fail. */ | 1326 | /* Validate mode, but don't set yet: setting flags may fail. */ |
| 1087 | if (data && data[IFLA_MACVLAN_MODE]) { | 1327 | if (data && data[IFLA_MACVLAN_MODE]) { |
| @@ -1091,6 +1331,9 @@ static int macvlan_changelink(struct net_device *dev, · 3 unmodified lines |
| 1091 | if ((mode == MACVLAN_MODE_PASSTHRU) != | 1331 | if ((mode == MACVLAN_MODE_PASSTHRU) != |
| 1092 | (vlan->mode == MACVLAN_MODE_PASSTHRU)) | 1332 | (vlan->mode == MACVLAN_MODE_PASSTHRU)) |
| 1093 | return -EINVAL; | 1333 | return -EINVAL; |
| | 1334 | if (vlan->mode == MACVLAN_MODE_SOURCE && |
| | 1335 | vlan->mode != mode) |
| | 1336 | macvlan_flush_sources(vlan->port, vlan); |
| 1094 | } | 1337 | } |
| 1095 | | 1338 | |
| 1096 | if (data && data[IFLA_MACVLAN_FLAGS]) { | 1339 | if (data && data[IFLA_MACVLAN_FLAGS]) { |
| @@ -1110,26 +1353,77 @@ static int macvlan_changelink(struct net_device *dev, · 13 unmodified lines |
| 1110 | } | 1353 | } |
| 1111 | if (set_mode) | 1354 | if (set_mode) |
| 1112 | vlan->mode = mode; | 1355 | vlan->mode = mode; |
| | 1356 | if (data && data[IFLA_MACVLAN_MACADDR_MODE]) { |
| | 1357 | if (vlan->mode != MACVLAN_MODE_SOURCE) |
| | 1358 | return -EINVAL; |
| | 1359 | macmode = nla_get_u32(data[IFLA_MACVLAN_MACADDR_MODE]); |
| | 1360 | ret = macvlan_changelink_sources(vlan, macmode, data); |
| | 1361 | if (ret) |
| | 1362 | return ret; |
| | 1363 | } |
| 1113 | return 0; | 1364 | return 0; |
| 1114 | } | 1365 | } |
| 1115 | | 1366 | |
| | 1367 | static size_t macvlan_get_size_mac(const struct macvlan_dev *vlan) |
| | 1368 | { |
| | 1369 | if (vlan->macaddr_count == 0) |
| | 1370 | return 0; |
| | 1371 | return nla_total_size(0) /* IFLA_MACVLAN_MACADDR_DATA */ |
| | 1372 | + vlan->macaddr_count * nla_total_size(sizeof(u8) * ETH_ALEN); |
| | 1373 | } |
| | 1374 | |
| 1116 | static size_t macvlan_get_size(const struct net_device *dev) | 1375 | static size_t macvlan_get_size(const struct net_device *dev) |
| 1117 | { | 1376 | { |
| | 1377 | struct macvlan_dev *vlan = netdev_priv(dev); |
| | 1378 | |
| 1118 | return (0 | 1379 | return (0 |
| 1119 | + nla_total_size(4) /* IFLA_MACVLAN_MODE */ | 1380 | + nla_total_size(4) /* IFLA_MACVLAN_MODE */ |
| 1120 | + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ | 1381 | + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ |
| | 1382 | + nla_total_size(4) /* IFLA_MACVLAN_MACADDR_COUNT */ |
| | 1383 | + macvlan_get_size_mac(vlan) /* IFLA_MACVLAN_MACADDR */ |
| 1121 | ); | 1384 | ); |
| 1122 | } | 1385 | } |
| 1123 | | 1386 | |
| | 1387 | static int macvlan_fill_info_macaddr(struct sk_buff *skb, |
| | 1388 | const struct macvlan_dev *vlan, |
| | 1389 | const int i) |
| | 1390 | { |
| | 1391 | struct hlist_head *h = &vlan->port->vlan_source_hash[i]; |
| | 1392 | struct macvlan_source_entry *entry; |
| | 1393 | |
| | 1394 | hlist_for_each_entry_rcu(entry, h, hlist) { |
| | 1395 | if (entry->vlan != vlan) |
| | 1396 | continue; |
| | 1397 | if (nla_put(skb, IFLA_MACVLAN_MACADDR, ETH_ALEN, entry->addr)) |
| | 1398 | return 1; |
| | 1399 | } |
| | 1400 | return 0; |
| | 1401 | } |
| | 1402 | |
| 1124 | static int macvlan_fill_info(struct sk_buff *skb, | 1403 | static int macvlan_fill_info(struct sk_buff *skb, |
| 1125 | const struct net_device *dev) | 1404 | const struct net_device *dev) |
| 1126 | { | 1405 | { |
| 1127 | struct macvlan_dev *vlan = netdev_priv(dev); | 1406 | struct macvlan_dev *vlan = netdev_priv(dev); |
| | 1407 | int i; |
| | 1408 | struct nlattr *nest; |
| 1128 | | 1409 | |
| 1129 | if (nla_put_u32(skb, IFLA_MACVLAN_MODE, vlan->mode)) | 1410 | if (nla_put_u32(skb, IFLA_MACVLAN_MODE, vlan->mode)) |
| 1130 | goto nla_put_failure; | 1411 | goto nla_put_failure; |
| 1131 | if (nla_put_u16(skb, IFLA_MACVLAN_FLAGS, vlan->flags)) | 1412 | if (nla_put_u16(skb, IFLA_MACVLAN_FLAGS, vlan->flags)) |
| 1132 | goto nla_put_failure; | 1413 | goto nla_put_failure; |
| | 1414 | if (nla_put_u32(skb, IFLA_MACVLAN_MACADDR_COUNT, vlan->macaddr_count)) |
| | 1415 | goto nla_put_failure; |
| | 1416 | if (vlan->macaddr_count > 0) { |
| | 1417 | nest = nla_nest_start(skb, IFLA_MACVLAN_MACADDR_DATA); |
| | 1418 | if (nest == NULL) |
| | 1419 | goto nla_put_failure; |
| | 1420 | |
| | 1421 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) { |
| | 1422 | if (macvlan_fill_info_macaddr(skb, vlan, i)) |
| | 1423 | goto nla_put_failure; |
| | 1424 | } |
| | 1425 | nla_nest_end(skb, nest); |
| | 1426 | } |
| 1133 | return 0; | 1427 | return 0; |
| 1134 | | 1428 | |
| 1135 | nla_put_failure: | 1429 | nla_put_failure: |
| @@ -1139,6 +1433,10 @@ nla_put_failure: · 3 unmodified lines |
| 1139 | static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { | 1433 | static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { |
| 1140 | [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, | 1434 | [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, |
| 1141 | [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 }, | 1435 | [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 }, |
| | 1436 | [IFLA_MACVLAN_MACADDR_MODE] = { .type = NLA_U32 }, |
| | 1437 | [IFLA_MACVLAN_MACADDR] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
| | 1438 | [IFLA_MACVLAN_MACADDR_DATA] = { .type = NLA_NESTED }, |
| | 1439 | [IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 }, |
| 1142 | }; | 1440 | }; |
| 1143 | | 1441 | |
| 1144 | int macvlan_link_register(struct rtnl_link_ops *ops) | 1442 | int macvlan_link_register(struct rtnl_link_ops *ops) |