Commit abf9d537fea225af60762640361af7fb233b3103
Committed by
David S. Miller
1 parent
e5cd6fe391
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 27 additions and 2 deletions Side-by-side Diff
net/llc/af_llc.c
... | ... | @@ -259,7 +259,14 @@ |
259 | 259 | if (!sock_flag(sk, SOCK_ZAPPED)) |
260 | 260 | goto out; |
261 | 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 | 270 | if (!llc->dev) |
264 | 271 | goto out; |
265 | 272 | rc = -EUSERS; |
... | ... | @@ -310,7 +317,25 @@ |
310 | 317 | goto out; |
311 | 318 | rc = -ENODEV; |
312 | 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 | 339 | rtnl_unlock(); |
315 | 340 | if (!llc->dev) |
316 | 341 | goto out; |