diff options
author | Octavian Purdila <opurdila@ixiacom.com> | 2009-12-26 06:51:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-26 23:41:12 -0500 |
commit | abf9d537fea225af60762640361af7fb233b3103 (patch) | |
tree | e0e47b3f869119b7a2902e759a637021037738ae /net/llc | |
parent | e5cd6fe391aa8c93560bb7ffdfe334cf4d0a02e4 (diff) |
llc: add support for SO_BINDTODEVICE
Using bind(MAC address) with LLC sockets has O(n) complexity, where n
is the number of interfaces. To overcome this, we add support for
SO_BINDTODEVICE which drops the complexity to O(1).
Signed-off-by: Octavian Purdila <opurdila@ixiacom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/llc')
-rw-r--r-- | net/llc/af_llc.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index ac691fe08076..c4d1a1da813c 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -259,7 +259,14 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) | |||
259 | if (!sock_flag(sk, SOCK_ZAPPED)) | 259 | if (!sock_flag(sk, SOCK_ZAPPED)) |
260 | goto out; | 260 | goto out; |
261 | rc = -ENODEV; | 261 | rc = -ENODEV; |
262 | llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); | 262 | if (sk->sk_bound_dev_if) { |
263 | llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); | ||
264 | if (llc->dev && addr->sllc_arphrd != llc->dev->type) { | ||
265 | dev_put(llc->dev); | ||
266 | llc->dev = NULL; | ||
267 | } | ||
268 | } else | ||
269 | llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); | ||
263 | if (!llc->dev) | 270 | if (!llc->dev) |
264 | goto out; | 271 | goto out; |
265 | rc = -EUSERS; | 272 | rc = -EUSERS; |
@@ -310,7 +317,25 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) | |||
310 | goto out; | 317 | goto out; |
311 | rc = -ENODEV; | 318 | rc = -ENODEV; |
312 | rtnl_lock(); | 319 | rtnl_lock(); |
313 | llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, addr->sllc_mac); | 320 | if (sk->sk_bound_dev_if) { |
321 | llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); | ||
322 | if (llc->dev) { | ||
323 | if (!addr->sllc_arphrd) | ||
324 | addr->sllc_arphrd = llc->dev->type; | ||
325 | if (llc_mac_null(addr->sllc_mac)) | ||
326 | memcpy(addr->sllc_mac, llc->dev->dev_addr, | ||
327 | IFHWADDRLEN); | ||
328 | if (addr->sllc_arphrd != llc->dev->type || | ||
329 | !llc_mac_match(addr->sllc_mac, | ||
330 | llc->dev->dev_addr)) { | ||
331 | rc = -EINVAL; | ||
332 | dev_put(llc->dev); | ||
333 | llc->dev = NULL; | ||
334 | } | ||
335 | } | ||
336 | } else | ||
337 | llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, | ||
338 | addr->sllc_mac); | ||
314 | rtnl_unlock(); | 339 | rtnl_unlock(); |
315 | if (!llc->dev) | 340 | if (!llc->dev) |
316 | goto out; | 341 | goto out; |