OSDN Git Service

bonding: add arp_all_targets netlink support
[uclinux-h8/linux.git] / drivers / net / bonding / bond_netlink.c
1 /*
2  * drivers/net/bond/bond_netlink.c - Netlink interface for bonding
3  * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
4  * Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14 #include <linux/module.h>
15 #include <linux/errno.h>
16 #include <linux/netdevice.h>
17 #include <linux/etherdevice.h>
18 #include <linux/if_link.h>
19 #include <linux/if_ether.h>
20 #include <net/netlink.h>
21 #include <net/rtnetlink.h>
22 #include "bonding.h"
23
24 static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
25         [IFLA_BOND_MODE]                = { .type = NLA_U8 },
26         [IFLA_BOND_ACTIVE_SLAVE]        = { .type = NLA_U32 },
27         [IFLA_BOND_MIIMON]              = { .type = NLA_U32 },
28         [IFLA_BOND_UPDELAY]             = { .type = NLA_U32 },
29         [IFLA_BOND_DOWNDELAY]           = { .type = NLA_U32 },
30         [IFLA_BOND_USE_CARRIER]         = { .type = NLA_U8 },
31         [IFLA_BOND_ARP_INTERVAL]        = { .type = NLA_U32 },
32         [IFLA_BOND_ARP_IP_TARGET]       = { .type = NLA_NESTED },
33         [IFLA_BOND_ARP_VALIDATE]        = { .type = NLA_U32 },
34         [IFLA_BOND_ARP_ALL_TARGETS]     = { .type = NLA_U32 },
35 };
36
37 static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
38 {
39         if (tb[IFLA_ADDRESS]) {
40                 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
41                         return -EINVAL;
42                 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
43                         return -EADDRNOTAVAIL;
44         }
45         return 0;
46 }
47
48 static int bond_changelink(struct net_device *bond_dev,
49                            struct nlattr *tb[], struct nlattr *data[])
50 {
51         struct bonding *bond = netdev_priv(bond_dev);
52         int miimon = 0;
53         int err;
54
55         if (!data)
56                 return 0;
57
58         if (data[IFLA_BOND_MODE]) {
59                 int mode = nla_get_u8(data[IFLA_BOND_MODE]);
60
61                 err = bond_option_mode_set(bond, mode);
62                 if (err)
63                         return err;
64         }
65         if (data[IFLA_BOND_ACTIVE_SLAVE]) {
66                 int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
67                 struct net_device *slave_dev;
68
69                 if (ifindex == 0) {
70                         slave_dev = NULL;
71                 } else {
72                         slave_dev = __dev_get_by_index(dev_net(bond_dev),
73                                                        ifindex);
74                         if (!slave_dev)
75                                 return -ENODEV;
76                 }
77                 err = bond_option_active_slave_set(bond, slave_dev);
78                 if (err)
79                         return err;
80         }
81         if (data[IFLA_BOND_MIIMON]) {
82                 miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
83
84                 err = bond_option_miimon_set(bond, miimon);
85                 if (err)
86                         return err;
87         }
88         if (data[IFLA_BOND_UPDELAY]) {
89                 int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);
90
91                 err = bond_option_updelay_set(bond, updelay);
92                 if (err)
93                         return err;
94         }
95         if (data[IFLA_BOND_DOWNDELAY]) {
96                 int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);
97
98                 err = bond_option_downdelay_set(bond, downdelay);
99                 if (err)
100                         return err;
101         }
102         if (data[IFLA_BOND_USE_CARRIER]) {
103                 int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
104
105                 err = bond_option_use_carrier_set(bond, use_carrier);
106                 if (err)
107                         return err;
108         }
109         if (data[IFLA_BOND_ARP_INTERVAL]) {
110                 int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
111
112                 if (arp_interval && miimon) {
113                         pr_err("%s: ARP monitoring cannot be used with MII monitoring.\n",
114                                bond->dev->name);
115                         return -EINVAL;
116                 }
117
118                 err = bond_option_arp_interval_set(bond, arp_interval);
119                 if (err)
120                         return err;
121         }
122         if (data[IFLA_BOND_ARP_IP_TARGET]) {
123                 __be32 targets[BOND_MAX_ARP_TARGETS] = { 0, };
124                 struct nlattr *attr;
125                 int i = 0, rem;
126
127                 nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
128                         __be32 target = nla_get_u32(attr);
129                         targets[i++] = target;
130                 }
131
132                 err = bond_option_arp_ip_targets_set(bond, targets, i);
133                 if (err)
134                         return err;
135         }
136         if (data[IFLA_BOND_ARP_VALIDATE]) {
137                 int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
138
139                 if (arp_validate && miimon) {
140                         pr_err("%s: ARP validating cannot be used with MII monitoring.\n",
141                                bond->dev->name);
142                         return -EINVAL;
143                 }
144
145                 err = bond_option_arp_validate_set(bond, arp_validate);
146                 if (err)
147                         return err;
148         }
149         if (data[IFLA_BOND_ARP_ALL_TARGETS]) {
150                 int arp_all_targets =
151                         nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]);
152
153                 err = bond_option_arp_all_targets_set(bond, arp_all_targets);
154                 if (err)
155                         return err;
156         }
157         return 0;
158 }
159
160 static int bond_newlink(struct net *src_net, struct net_device *bond_dev,
161                         struct nlattr *tb[], struct nlattr *data[])
162 {
163         int err;
164
165         err = bond_changelink(bond_dev, tb, data);
166         if (err < 0)
167                 return err;
168
169         return register_netdevice(bond_dev);
170 }
171
172 static size_t bond_get_size(const struct net_device *bond_dev)
173 {
174         return nla_total_size(sizeof(u8)) +     /* IFLA_BOND_MODE */
175                 nla_total_size(sizeof(u32)) +   /* IFLA_BOND_ACTIVE_SLAVE */
176                 nla_total_size(sizeof(u32)) +   /* IFLA_BOND_MIIMON */
177                 nla_total_size(sizeof(u32)) +   /* IFLA_BOND_UPDELAY */
178                 nla_total_size(sizeof(u32)) +   /* IFLA_BOND_DOWNDELAY */
179                 nla_total_size(sizeof(u8)) +    /* IFLA_BOND_USE_CARRIER */
180                 nla_total_size(sizeof(u32)) +   /* IFLA_BOND_ARP_INTERVAL */
181                                                 /* IFLA_BOND_ARP_IP_TARGET */
182                 nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS +
183                 nla_total_size(sizeof(u32)) +   /* IFLA_BOND_ARP_VALIDATE */
184                 nla_total_size(sizeof(u32)) +   /* IFLA_BOND_ARP_ALL_TARGETS */
185                 0;
186 }
187
188 static int bond_fill_info(struct sk_buff *skb,
189                           const struct net_device *bond_dev)
190 {
191         struct bonding *bond = netdev_priv(bond_dev);
192         struct net_device *slave_dev = bond_option_active_slave_get(bond);
193         struct nlattr *targets;
194         int i, targets_added;
195
196         if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode))
197                 goto nla_put_failure;
198
199         if (slave_dev &&
200             nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))
201                 goto nla_put_failure;
202
203         if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
204                 goto nla_put_failure;
205
206         if (nla_put_u32(skb, IFLA_BOND_UPDELAY,
207                         bond->params.updelay * bond->params.miimon))
208                 goto nla_put_failure;
209
210         if (nla_put_u32(skb, IFLA_BOND_DOWNDELAY,
211                         bond->params.downdelay * bond->params.miimon))
212                 goto nla_put_failure;
213
214         if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier))
215                 goto nla_put_failure;
216
217         if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval))
218                 goto nla_put_failure;
219
220         targets = nla_nest_start(skb, IFLA_BOND_ARP_IP_TARGET);
221         if (!targets)
222                 goto nla_put_failure;
223
224         targets_added = 0;
225         for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
226                 if (bond->params.arp_targets[i]) {
227                         nla_put_u32(skb, i, bond->params.arp_targets[i]);
228                         targets_added = 1;
229                 }
230         }
231
232         if (targets_added)
233                 nla_nest_end(skb, targets);
234         else
235                 nla_nest_cancel(skb, targets);
236
237         if (nla_put_u32(skb, IFLA_BOND_ARP_VALIDATE, bond->params.arp_validate))
238                 goto nla_put_failure;
239
240         if (nla_put_u32(skb, IFLA_BOND_ARP_ALL_TARGETS,
241                         bond->params.arp_all_targets))
242                 goto nla_put_failure;
243
244         return 0;
245
246 nla_put_failure:
247         return -EMSGSIZE;
248 }
249
250 struct rtnl_link_ops bond_link_ops __read_mostly = {
251         .kind                   = "bond",
252         .priv_size              = sizeof(struct bonding),
253         .setup                  = bond_setup,
254         .maxtype                = IFLA_BOND_MAX,
255         .policy                 = bond_policy,
256         .validate               = bond_validate,
257         .newlink                = bond_newlink,
258         .changelink             = bond_changelink,
259         .get_size               = bond_get_size,
260         .fill_info              = bond_fill_info,
261         .get_num_tx_queues      = bond_get_num_tx_queues,
262         .get_num_rx_queues      = bond_get_num_tx_queues, /* Use the same number
263                                                              as for TX queues */
264 };
265
266 int __init bond_netlink_init(void)
267 {
268         return rtnl_link_register(&bond_link_ops);
269 }
270
271 void bond_netlink_fini(void)
272 {
273         rtnl_link_unregister(&bond_link_ops);
274 }
275
276 MODULE_ALIAS_RTNL_LINK("bond");