Skip to content

Commit 3b01baa

Browse files
committed
Merge citrix branch into master.
2 parents 080ec39 + 3c303e5 commit 3b01baa

48 files changed

Lines changed: 1287 additions & 359 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

datapath/brcompat.c

Lines changed: 151 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ static DEFINE_MUTEX(brc_serial);
4040
/* Userspace communication. */
4141
static DEFINE_SPINLOCK(brc_lock); /* Ensure atomic access to these vars. */
4242
static DECLARE_COMPLETION(brc_done); /* Userspace signaled operation done? */
43-
static int brc_err; /* Error code from userspace. */
43+
static struct sk_buff *brc_reply; /* Reply from userspace. */
4444
static u32 brc_seq; /* Sequence number for current op. */
4545

46-
static int brc_send_command(const char *bridge, const char *port, int op);
46+
static struct sk_buff *brc_send_command(struct sk_buff *, struct nlattr **attrs);
47+
static int brc_send_simple_command(struct sk_buff *);
4748

4849
static int
4950
get_dp_ifindices(int *indices, int num)
@@ -75,16 +76,55 @@ get_port_ifindices(struct datapath *dp, int *ifindices, int num)
7576
rcu_read_unlock();
7677
}
7778

79+
static struct sk_buff *
80+
brc_make_request(int op, const char *bridge, const char *port)
81+
{
82+
struct sk_buff *skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
83+
if (!skb)
84+
goto error;
85+
86+
genlmsg_put(skb, 0, 0, &brc_genl_family, 0, op);
87+
NLA_PUT_STRING(skb, BRC_GENL_A_DP_NAME, bridge);
88+
if (port)
89+
NLA_PUT_STRING(skb, BRC_GENL_A_PORT_NAME, port);
90+
return skb;
91+
92+
nla_put_failure:
93+
kfree_skb(skb);
94+
error:
95+
return NULL;
96+
}
97+
98+
static int brc_send_simple_command(struct sk_buff *request)
99+
{
100+
struct nlattr *attrs[BRC_GENL_A_MAX + 1];
101+
struct sk_buff *reply;
102+
int error;
103+
104+
reply = brc_send_command(request, attrs);
105+
if (IS_ERR(reply))
106+
return PTR_ERR(reply);
107+
108+
error = nla_get_u32(attrs[BRC_GENL_A_ERR_CODE]);
109+
kfree_skb(reply);
110+
return -error;
111+
}
112+
78113
static int brc_add_del_bridge(char __user *uname, int add)
79114
{
115+
struct sk_buff *request;
80116
char name[IFNAMSIZ];
81117

82118
if (copy_from_user(name, uname, IFNAMSIZ))
83119
return -EFAULT;
84120

85121
name[IFNAMSIZ - 1] = 0;
86-
return brc_send_command(name, NULL,
87-
add ? BRC_GENL_C_DP_ADD : BRC_GENL_C_DP_DEL);
122+
request = brc_make_request(add ? BRC_GENL_C_DP_ADD : BRC_GENL_C_DP_DEL,
123+
name, NULL);
124+
if (!request)
125+
return -ENOMEM;
126+
127+
return brc_send_simple_command(request);
88128
}
89129

90130
static int brc_get_bridges(int __user *uindices, int n)
@@ -154,22 +194,23 @@ brc_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
154194
static int
155195
brc_add_del_port(struct net_device *dev, int port_ifindex, int add)
156196
{
197+
struct sk_buff *request;
157198
struct net_device *port;
158-
char dev_name[IFNAMSIZ], port_name[IFNAMSIZ];
159199
int err;
160200

161201
port = __dev_get_by_index(&init_net, port_ifindex);
162202
if (!port)
163203
return -EINVAL;
164204

165205
/* Save name of dev and port because there's a race between the
166-
* rtnl_unlock() and the brc_send_command(). */
167-
strcpy(dev_name, dev->name);
168-
strcpy(port_name, port->name);
206+
* rtnl_unlock() and the brc_send_simple_command(). */
207+
request = brc_make_request(add ? BRC_GENL_C_PORT_ADD : BRC_GENL_C_PORT_DEL,
208+
dev->name, port->name);
209+
if (!request)
210+
return -ENOMEM;
169211

170212
rtnl_unlock();
171-
err = brc_send_command(dev_name, port_name,
172-
add ? BRC_GENL_C_PORT_ADD : BRC_GENL_C_PORT_DEL);
213+
err = brc_send_simple_command(request);
173214
rtnl_lock();
174215

175216
return err;
@@ -220,6 +261,64 @@ brc_get_port_list(struct net_device *dev, int __user *uindices, int num)
220261
return num;
221262
}
222263

264+
/*
265+
* Format up to a page worth of forwarding table entries
266+
* userbuf -- where to copy result
267+
* maxnum -- maximum number of entries desired
268+
* (limited to a page for sanity)
269+
* offset -- number of records to skip
270+
*/
271+
static int brc_get_fdb_entries(struct net_device *dev, void __user *userbuf,
272+
unsigned long maxnum, unsigned long offset)
273+
{
274+
struct nlattr *attrs[BRC_GENL_A_MAX + 1];
275+
struct sk_buff *request, *reply;
276+
int retval;
277+
int len;
278+
279+
/* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
280+
if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
281+
maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
282+
283+
request = brc_make_request(BRC_GENL_C_FDB_QUERY, dev->name, NULL);
284+
if (!request)
285+
return -ENOMEM;
286+
NLA_PUT_U64(request, BRC_GENL_A_FDB_COUNT, maxnum);
287+
NLA_PUT_U64(request, BRC_GENL_A_FDB_SKIP, offset);
288+
289+
rtnl_unlock();
290+
reply = brc_send_command(request, attrs);
291+
retval = PTR_ERR(reply);
292+
if (IS_ERR(reply))
293+
goto exit;
294+
295+
retval = -nla_get_u32(attrs[BRC_GENL_A_ERR_CODE]);
296+
if (retval < 0)
297+
goto exit_free_skb;
298+
299+
retval = -EINVAL;
300+
if (!attrs[BRC_GENL_A_FDB_DATA])
301+
goto exit_free_skb;
302+
len = nla_len(attrs[BRC_GENL_A_FDB_DATA]);
303+
if (len % sizeof(struct __fdb_entry) ||
304+
len / sizeof(struct __fdb_entry) > maxnum)
305+
goto exit_free_skb;
306+
307+
retval = len / sizeof(struct __fdb_entry);
308+
if (copy_to_user(userbuf, nla_data(attrs[BRC_GENL_A_FDB_DATA]), len))
309+
retval = -EFAULT;
310+
311+
exit_free_skb:
312+
kfree_skb(reply);
313+
exit:
314+
rtnl_lock();
315+
return retval;
316+
317+
nla_put_failure:
318+
kfree_skb(request);
319+
return -ENOMEM;
320+
}
321+
223322
/* Legacy ioctl's through SIOCDEVPRIVATE. Called with rtnl_lock. */
224323
static int
225324
old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -240,6 +339,10 @@ old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
240339

241340
case BRCTL_GET_PORT_LIST:
242341
return brc_get_port_list(dev, (int __user *)args[1], args[2]);
342+
343+
case BRCTL_GET_FDB_ENTRIES:
344+
return brc_get_fdb_entries(dev, (void __user *)args[1],
345+
args[2], args[3]);
243346
}
244347

245348
return -EOPNOTSUPP;
@@ -316,9 +419,12 @@ static struct genl_ops brc_genl_ops_query_dp = {
316419
/* Attribute policy: what each attribute may contain. */
317420
static struct nla_policy brc_genl_policy[BRC_GENL_A_MAX + 1] = {
318421
[BRC_GENL_A_ERR_CODE] = { .type = NLA_U32 },
422+
319423
[BRC_GENL_A_PROC_DIR] = { .type = NLA_NUL_STRING },
320424
[BRC_GENL_A_PROC_NAME] = { .type = NLA_NUL_STRING },
321425
[BRC_GENL_A_PROC_DATA] = { .type = NLA_NUL_STRING },
426+
427+
[BRC_GENL_A_FDB_DATA] = { .type = NLA_UNSPEC },
322428
};
323429

324430
static int
@@ -330,12 +436,22 @@ brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info)
330436
if (!info->attrs[BRC_GENL_A_ERR_CODE])
331437
return -EINVAL;
332438

439+
skb = skb_clone(skb, GFP_KERNEL);
440+
if (!skb)
441+
return -ENOMEM;
442+
333443
spin_lock_irqsave(&brc_lock, flags);
334444
if (brc_seq == info->snd_seq) {
335-
brc_err = nla_get_u32(info->attrs[BRC_GENL_A_ERR_CODE]);
445+
brc_seq++;
446+
447+
if (brc_reply)
448+
kfree_skb(brc_reply);
449+
brc_reply = skb;
450+
336451
complete(&brc_done);
337452
err = 0;
338453
} else {
454+
kfree_skb(skb);
339455
err = -ESTALE;
340456
}
341457
spin_unlock_irqrestore(&brc_lock, flags);
@@ -359,53 +475,52 @@ static struct genl_ops brc_genl_ops_set_proc = {
359475
.dumpit = NULL
360476
};
361477

362-
static int brc_send_command(const char *bridge, const char *port, int op)
478+
static struct sk_buff *brc_send_command(struct sk_buff *request, struct nlattr **attrs)
363479
{
364480
unsigned long int flags;
365-
struct sk_buff *skb;
366-
void *data;
481+
struct sk_buff *reply;
367482
int error;
368483

369484
mutex_lock(&brc_serial);
370485

371486
/* Increment sequence number first, so that we ignore any replies
372487
* to stale requests. */
373488
spin_lock_irqsave(&brc_lock, flags);
374-
brc_seq++;
489+
nlmsg_hdr(request)->nlmsg_seq = ++brc_seq;
375490
INIT_COMPLETION(brc_done);
376491
spin_unlock_irqrestore(&brc_lock, flags);
377492

378-
/* Compose message. */
379-
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
380-
error = -ENOMEM;
381-
if (skb == NULL)
382-
goto exit_unlock;
383-
data = genlmsg_put(skb, 0, brc_seq, &brc_genl_family, 0, op);
384-
385-
NLA_PUT_STRING(skb, BRC_GENL_A_DP_NAME, bridge);
386-
if (port)
387-
NLA_PUT_STRING(skb, BRC_GENL_A_PORT_NAME, port);
388-
389-
genlmsg_end(skb, data);
493+
nlmsg_end(request, nlmsg_hdr(request));
390494

391495
/* Send message. */
392-
error = genlmsg_multicast(skb, 0, brc_mc_group.id, GFP_KERNEL);
496+
error = genlmsg_multicast(request, 0, brc_mc_group.id, GFP_KERNEL);
393497
if (error < 0)
394-
goto exit_unlock;
498+
goto error;
395499

396500
/* Wait for reply. */
397501
error = -ETIMEDOUT;
398502
if (!wait_for_completion_timeout(&brc_done, BRC_TIMEOUT))
399-
goto exit_unlock;
503+
goto error;
504+
505+
/* Grab reply. */
506+
spin_lock_irqsave(&brc_lock, flags);
507+
reply = brc_reply;
508+
brc_reply = NULL;
509+
spin_unlock_irqrestore(&brc_lock, flags);
400510

401-
error = -brc_err;
402-
goto exit_unlock;
511+
mutex_unlock(&brc_serial);
403512

404-
nla_put_failure:
405-
kfree_skb(skb);
406-
exit_unlock:
513+
/* Re-parse message. Can't fail, since it parsed correctly once
514+
* already. */
515+
error = nlmsg_parse(nlmsg_hdr(reply), GENL_HDRLEN,
516+
attrs, BRC_GENL_A_MAX, brc_genl_policy);
517+
WARN_ON(error);
518+
519+
return reply;
520+
521+
error:
407522
mutex_unlock(&brc_serial);
408-
return error;
523+
return ERR_PTR(error);
409524
}
410525

411526
int brc_add_dp(struct datapath *dp)

0 commit comments

Comments
 (0)