summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2012-11-15 03:49:10 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-15 17:36:16 -0500
commit62532da9d5f47a7ced3b965aa73ffd5b1afbeb79 (patch)
tree520e8ca8c90116fb4f92db0c356474abed905c79
parentefad0c14b720ec3791c95e0658c3990fbc124366 (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>
-rw-r--r--include/linux/netdevice.h14
-rw-r--r--net/core/dev.c80
2 files changed, 94 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7bf867c97043..d45a58db4ba3 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1521,6 +1521,17 @@ struct packet_type {
1521 struct list_head list; 1521 struct list_head list;
1522}; 1522};
1523 1523
1524struct packet_offload {
1525 __be16 type; /* This is really htons(ether_type). */
1526 struct sk_buff *(*gso_segment)(struct sk_buff *skb,
1527 netdev_features_t features);
1528 int (*gso_send_check)(struct sk_buff *skb);
1529 struct sk_buff **(*gro_receive)(struct sk_buff **head,
1530 struct sk_buff *skb);
1531 int (*gro_complete)(struct sk_buff *skb);
1532 struct list_head list;
1533};
1534
1524#include <linux/notifier.h> 1535#include <linux/notifier.h>
1525 1536
1526/* netdevice notifier chain. Please remember to update the rtnetlink 1537/* netdevice notifier chain. Please remember to update the rtnetlink
@@ -1615,6 +1626,9 @@ extern struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short
1615extern void dev_add_pack(struct packet_type *pt); 1626extern void dev_add_pack(struct packet_type *pt);
1616extern void dev_remove_pack(struct packet_type *pt); 1627extern void dev_remove_pack(struct packet_type *pt);
1617extern void __dev_remove_pack(struct packet_type *pt); 1628extern void __dev_remove_pack(struct packet_type *pt);
1629extern void dev_add_offload(struct packet_offload *po);
1630extern void dev_remove_offload(struct packet_offload *po);
1631extern void __dev_remove_offload(struct packet_offload *po);
1618 1632
1619extern struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags, 1633extern struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags,
1620 unsigned short mask); 1634 unsigned short mask);
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
178static DEFINE_SPINLOCK(ptype_lock); 178static DEFINE_SPINLOCK(ptype_lock);
179static DEFINE_SPINLOCK(offload_lock);
179static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; 180static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly;
180static struct list_head ptype_all __read_mostly; /* Taps */ 181static struct list_head ptype_all __read_mostly; /* Taps */
182static 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}
471EXPORT_SYMBOL(dev_remove_pack); 473EXPORT_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 */
488void 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}
496EXPORT_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 */
511void __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);
526out:
527 spin_unlock(&ptype_lock);
528}
529EXPORT_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 */
543void dev_remove_offload(struct packet_offload *po)
544{
545 __dev_remove_offload(po);
546
547 synchronize_net();
548}
549EXPORT_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