aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Braun <michael-dev@fami-braun.de>2014-09-25 10:31:08 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-29 15:37:01 -0400
commit79cf79abce71eb7dbc40e2f3121048ca5405cb47 (patch)
tree81e5b392884d9b0c2f7e4bbd925f4c7c55229834
parent852248449c73b5ffe109a33d65485c71d3d398a7 (diff)
macvlan: add source mode
This patch adds a new mode of operation to macvlan, called "source". It allows one to set a list of allowed mac address, which is used to match against source mac address from received frames on underlying interface. This enables creating mac based VLAN associations, instead of standard port or tag based. The feature is useful to deploy 802.1x mac based behavior, where drivers of underlying interfaces doesn't allows that. Configuration is done through the netlink interface using e.g.: ip link add link eth0 name macvlan0 type macvlan mode source ip link add link eth0 name macvlan1 type macvlan mode source ip link set link dev macvlan0 type macvlan macaddr add 00:11:11:11:11:11 ip link set link dev macvlan0 type macvlan macaddr add 00:22:22:22:22:22 ip link set link dev macvlan0 type macvlan macaddr add 00:33:33:33:33:33 ip link set link dev macvlan1 type macvlan macaddr add 00:33:33:33:33:33 ip link set link dev macvlan1 type macvlan macaddr add 00:44:44:44:44:44 This allows clients with MAC addresses 00:11:11:11:11:11, 00:22:22:22:22:22 to be part of only VLAN associated with macvlan0 interface. Clients with MAC addresses 00:44:44:44:44:44 with only VLAN associated with macvlan1 interface. And client with MAC address 00:33:33:33:33:33 to be associated with both VLANs. Based on work of Stefan Gula <steweg@gmail.com> v8: last version of Stefan Gula for Kernel 3.2.1 v9: rework onto linux-next 2014-03-12 by Michael Braun add MACADDR_SET command, enable to configure mac for source mode while creating interface v10: - reduce indention level - rename source_list to source_entry - use aligned 64bit ether address - use hash_64 instead of addr[5] v11: - rebase for 3.14 / linux-next 20.04.2014 v12 - rebase for linux-next 2014-09-25 Signed-off-by: Michael Braun <michael-dev@fami-braun.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/macvlan.c304
-rw-r--r--include/linux/if_macvlan.h1
-rw-r--r--include/uapi/linux/if_link.h12
3 files changed, 314 insertions, 3 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 726edabff26b..e8a453f1b458 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -35,7 +35,8 @@
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
41struct macvlan_port { 42struct macvlan_port {
@@ -47,6 +48,14 @@ struct macvlan_port {
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
54struct 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
52struct macvlan_skb_cb { 61struct macvlan_skb_cb {
@@ -57,6 +66,20 @@ struct macvlan_skb_cb {
57 66
58static void macvlan_port_destroy(struct net_device *dev); 67static void macvlan_port_destroy(struct net_device *dev);
59 68
69/* Hash Ethernet address */
70static 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
60static struct macvlan_port *macvlan_port_get_rcu(const struct net_device *dev) 83static 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,
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
108static 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
124static 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
84static void macvlan_hash_add(struct macvlan_dev *vlan) 148static 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
157static 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
92static void macvlan_hash_del(struct macvlan_dev *vlan, bool sync) 163static void macvlan_hash_del(struct macvlan_dev *vlan, bool sync)
@@ -267,6 +338,65 @@ err:
267 atomic_long_inc(&skb->dev->rx_dropped); 338 atomic_long_inc(&skb->dev->rx_dropped);
268} 339}
269 340
341static 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
361static 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
385static 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 */
271static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) 401static 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)
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)
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)
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)
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[])
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 */
1143static 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,
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,
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)
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,
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,
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,
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
1367static 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
1116static size_t macvlan_get_size(const struct net_device *dev) 1375static 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
1387static 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
1124static int macvlan_fill_info(struct sk_buff *skb, 1403static 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
1135nla_put_failure: 1429nla_put_failure:
@@ -1139,6 +1433,10 @@ nla_put_failure:
1139static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { 1433static 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
1144int macvlan_link_register(struct rtnl_link_ops *ops) 1442int macvlan_link_register(struct rtnl_link_ops *ops)
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 6b2c7cf352a5..6f6929ea8a0c 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -60,6 +60,7 @@ struct macvlan_dev {
60#ifdef CONFIG_NET_POLL_CONTROLLER 60#ifdef CONFIG_NET_POLL_CONTROLLER
61 struct netpoll *netpoll; 61 struct netpoll *netpoll;
62#endif 62#endif
63 unsigned int macaddr_count;
63}; 64};
64 65
65static inline void macvlan_count_rx(const struct macvlan_dev *vlan, 66static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index c80f95f6ee78..0bdb77e16875 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -303,6 +303,10 @@ enum {
303 IFLA_MACVLAN_UNSPEC, 303 IFLA_MACVLAN_UNSPEC,
304 IFLA_MACVLAN_MODE, 304 IFLA_MACVLAN_MODE,
305 IFLA_MACVLAN_FLAGS, 305 IFLA_MACVLAN_FLAGS,
306 IFLA_MACVLAN_MACADDR_MODE,
307 IFLA_MACVLAN_MACADDR,
308 IFLA_MACVLAN_MACADDR_DATA,
309 IFLA_MACVLAN_MACADDR_COUNT,
306 __IFLA_MACVLAN_MAX, 310 __IFLA_MACVLAN_MAX,
307}; 311};
308 312
@@ -313,6 +317,14 @@ enum macvlan_mode {
313 MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ 317 MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */
314 MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ 318 MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */
315 MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ 319 MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */
320 MACVLAN_MODE_SOURCE = 16,/* use source MAC address list to assign */
321};
322
323enum macvlan_macaddr_mode {
324 MACVLAN_MACADDR_ADD,
325 MACVLAN_MACADDR_DEL,
326 MACVLAN_MACADDR_FLUSH,
327 MACVLAN_MACADDR_SET,
316}; 328};
317 329
318#define MACVLAN_FLAG_NOPROMISC 1 330#define MACVLAN_FLAG_NOPROMISC 1