aboutsummaryrefslogtreecommitdiffstats
path: root/net/llc/af_llc.c
diff options
context:
space:
mode:
authorOctavian Purdila <opurdila@ixiacom.com>2009-12-26 06:51:01 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-26 23:41:12 -0500
commitabf9d537fea225af60762640361af7fb233b3103 (patch)
treee0e47b3f869119b7a2902e759a637021037738ae /net/llc/af_llc.c
parente5cd6fe391aa8c93560bb7ffdfe334cf4d0a02e4 (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/af_llc.c')
-rw-r--r--net/llc/af_llc.c29
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;