diff options
author | Vlad Yasevich <vyasevic@redhat.com> | 2012-11-15 03:49:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-15 17:36:16 -0500 |
commit | 62532da9d5f47a7ced3b965aa73ffd5b1afbeb79 (patch) | |
tree | 520e8ca8c90116fb4f92db0c356474abed905c79 /net/core | |
parent | efad0c14b720ec3791c95e0658c3990fbc124366 (diff) |
net: Add generic packet offload infrastructure.
Create a new data structure to contain the GRO/GSO callbacks and add
a new registration mechanism.
Singed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 83232a1be1e7..6884f8783bdd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -176,8 +176,10 @@ | |||
176 | #define PTYPE_HASH_MASK (PTYPE_HASH_SIZE - 1) | 176 | #define PTYPE_HASH_MASK (PTYPE_HASH_SIZE - 1) |
177 | 177 | ||
178 | static DEFINE_SPINLOCK(ptype_lock); | 178 | static DEFINE_SPINLOCK(ptype_lock); |
179 | static DEFINE_SPINLOCK(offload_lock); | ||
179 | static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; | 180 | static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; |
180 | static struct list_head ptype_all __read_mostly; /* Taps */ | 181 | static struct list_head ptype_all __read_mostly; /* Taps */ |
182 | static struct list_head offload_base __read_mostly; | ||
181 | 183 | ||
182 | /* | 184 | /* |
183 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl | 185 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl |
@@ -470,6 +472,82 @@ void dev_remove_pack(struct packet_type *pt) | |||
470 | } | 472 | } |
471 | EXPORT_SYMBOL(dev_remove_pack); | 473 | EXPORT_SYMBOL(dev_remove_pack); |
472 | 474 | ||
475 | |||
476 | /** | ||
477 | * dev_add_offload - register offload handlers | ||
478 | * @po: protocol offload declaration | ||
479 | * | ||
480 | * Add protocol offload handlers to the networking stack. The passed | ||
481 | * &proto_offload is linked into kernel lists and may not be freed until | ||
482 | * it has been removed from the kernel lists. | ||
483 | * | ||
484 | * This call does not sleep therefore it can not | ||
485 | * guarantee all CPU's that are in middle of receiving packets | ||
486 | * will see the new offload handlers (until the next received packet). | ||
487 | */ | ||
488 | void dev_add_offload(struct packet_offload *po) | ||
489 | { | ||
490 | struct list_head *head = &offload_base; | ||
491 | |||
492 | spin_lock(&offload_lock); | ||
493 | list_add_rcu(&po->list, head); | ||
494 | spin_unlock(&offload_lock); | ||
495 | } | ||
496 | EXPORT_SYMBOL(dev_add_offload); | ||
497 | |||
498 | /** | ||
499 | * __dev_remove_offload - remove offload handler | ||
500 | * @po: packet offload declaration | ||
501 | * | ||
502 | * Remove a protocol offload handler that was previously added to the | ||
503 | * kernel offload handlers by dev_add_offload(). The passed &offload_type | ||
504 | * is removed from the kernel lists and can be freed or reused once this | ||
505 | * function returns. | ||
506 | * | ||
507 | * The packet type might still be in use by receivers | ||
508 | * and must not be freed until after all the CPU's have gone | ||
509 | * through a quiescent state. | ||
510 | */ | ||
511 | void __dev_remove_offload(struct packet_offload *po) | ||
512 | { | ||
513 | struct list_head *head = &offload_base; | ||
514 | struct packet_offload *po1; | ||
515 | |||
516 | spin_lock(&ptype_lock); | ||
517 | |||
518 | list_for_each_entry(po1, head, list) { | ||
519 | if (po == po1) { | ||
520 | list_del_rcu(&po->list); | ||
521 | goto out; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | pr_warn("dev_remove_offload: %p not found\n", po); | ||
526 | out: | ||
527 | spin_unlock(&ptype_lock); | ||
528 | } | ||
529 | EXPORT_SYMBOL(__dev_remove_offload); | ||
530 | |||
531 | /** | ||
532 | * dev_remove_offload - remove packet offload handler | ||
533 | * @po: packet offload declaration | ||
534 | * | ||
535 | * Remove a packet offload handler that was previously added to the kernel | ||
536 | * offload handlers by dev_add_offload(). The passed &offload_type is | ||
537 | * removed from the kernel lists and can be freed or reused once this | ||
538 | * function returns. | ||
539 | * | ||
540 | * This call sleeps to guarantee that no CPU is looking at the packet | ||
541 | * type after return. | ||
542 | */ | ||
543 | void dev_remove_offload(struct packet_offload *po) | ||
544 | { | ||
545 | __dev_remove_offload(po); | ||
546 | |||
547 | synchronize_net(); | ||
548 | } | ||
549 | EXPORT_SYMBOL(dev_remove_offload); | ||
550 | |||
473 | /****************************************************************************** | 551 | /****************************************************************************** |
474 | 552 | ||
475 | Device Boot-time Settings Routines | 553 | Device Boot-time Settings Routines |
@@ -6661,6 +6739,8 @@ static int __init net_dev_init(void) | |||
6661 | for (i = 0; i < PTYPE_HASH_SIZE; i++) | 6739 | for (i = 0; i < PTYPE_HASH_SIZE; i++) |
6662 | INIT_LIST_HEAD(&ptype_base[i]); | 6740 | INIT_LIST_HEAD(&ptype_base[i]); |
6663 | 6741 | ||
6742 | INIT_LIST_HEAD(&offload_base); | ||
6743 | |||
6664 | if (register_pernet_subsys(&netdev_net_ops)) | 6744 | if (register_pernet_subsys(&netdev_net_ops)) |
6665 | goto out; | 6745 | goto out; |
6666 | 6746 | ||