From be9eac48274a2d9b142d6dd8567b9b2362939346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= Date: Fri, 15 Nov 2013 06:18:40 +0100 Subject: macvlan: introduce macvlan_dev_real_dev() helper function Introduce helper function macvlan_dev_real_dev which returns the underlying device of a macvlan device, similar to vlan_dev_real_dev() for 802.1q VLAN devices. v2: IFF_MACVLAN flag and equivalent of is_macvlan_dev() were introduced in the meantime v3: do BUG() if compiled without macvlan support Signed-off-by: Michal Kubecek Signed-off-by: David S. Miller --- include/linux/if_macvlan.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'include/linux') diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index c2702856295e..84ba5ac39e03 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -119,4 +119,21 @@ extern int macvlan_link_register(struct rtnl_link_ops *ops); extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev); +#if IS_ENABLED(CONFIG_MACVLAN) +static inline struct net_device * +macvlan_dev_real_dev(const struct net_device *dev) +{ + struct macvlan_dev *macvlan = netdev_priv(dev); + + return macvlan->lowerdev; +} +#else +static inline struct net_device * +macvlan_dev_real_dev(const struct net_device *dev) +{ + BUG(); + return NULL; +} +#endif + #endif /* _LINUX_IF_MACVLAN_H */ -- cgit v1.2.3 From 018c5bba052b3a383d83cf0c756da0e7bc748397 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 15 Nov 2013 21:11:16 -0500 Subject: net: Handle CHECKSUM_COMPLETE more adequately in pskb_trim_rcsum(). Currently pskb_trim_rcsum() just balks on CHECKSUM_COMPLETE packets and remarks them as CHECKSUM_NONE, forcing a software checksum validation later. We have all of the mechanics available to fixup the skb->csum value, even for complicated fragmented packets, via the helpers skb_checksum() and csum_sub(). So just use them. Based upon a suggestion by Herbert Xu. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 215b5ea1cb30..bec1cc7d5e3c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2263,24 +2263,6 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb, unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); -/** - * pskb_trim_rcsum - trim received skb and update checksum - * @skb: buffer to trim - * @len: new length - * - * This is exactly the same as pskb_trim except that it ensures the - * checksum of received packets are still valid after the operation. - */ - -static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) -{ - if (likely(len >= skb->len)) - return 0; - if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->ip_summed = CHECKSUM_NONE; - return __pskb_trim(skb, len); -} - #define skb_queue_walk(queue, skb) \ for (skb = (queue)->next; \ skb != (struct sk_buff *)(queue); \ @@ -2378,6 +2360,27 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum csum); +/** + * pskb_trim_rcsum - trim received skb and update checksum + * @skb: buffer to trim + * @len: new length + * + * This is exactly the same as pskb_trim except that it ensures the + * checksum of received packets are still valid after the operation. + */ + +static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) +{ + if (likely(len >= skb->len)) + return 0; + if (skb->ip_summed == CHECKSUM_COMPLETE) { + __wsum adj = skb_checksum(skb, len, skb->len - len, 0); + + skb->csum = csum_sub(skb->csum, adj); + } + return __pskb_trim(skb, len); +} + static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) { -- cgit v1.2.3 From c53ed7423619b4e8108914a9f31b426dd58ad591 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Nov 2013 15:19:31 +0100 Subject: genetlink: only pass array to genl_register_family_with_ops() As suggested by David Miller, make genl_register_family_with_ops() a macro and pass only the array, evaluating ARRAY_SIZE() in the macro, this is a little safer. The openvswitch has some indirection, assing ops/n_ops directly in that code. This might ultimately just assign the pointers in the family initializations, saving the struct genl_family_and_ops and code (once mcast groups are handled differently.) Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- include/linux/genl_magic_func.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h index 023bc346b877..47086030ab31 100644 --- a/include/linux/genl_magic_func.h +++ b/include/linux/genl_magic_func.h @@ -293,8 +293,7 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) { - int err = genl_register_family_with_ops(&ZZZ_genl_family, - ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops)); + int err = genl_register_family_with_ops(&ZZZ_genl_family, ZZZ_genl_ops); if (err) return err; #undef GENL_mc_group -- cgit v1.2.3 From 68eb55031da7c967d954e5f9415cd05f4abdb692 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Nov 2013 15:19:38 +0100 Subject: genetlink: pass family to functions using groups This doesn't really change anything, but prepares for the next patch that will change the APIs to pass the group ID within the family, rather than the global group ID. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- include/linux/genl_magic_func.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h index 47086030ab31..5b9b8ae6748b 100644 --- a/include/linux/genl_magic_func.h +++ b/include/linux/genl_magic_func.h @@ -286,7 +286,8 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \ if (!group_id) \ return -EINVAL; \ - return genlmsg_multicast(skb, 0, group_id, flags); \ + return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \ + group_id, flags); \ } #include GENL_MAGIC_INCLUDE_FILE -- cgit v1.2.3 From 2a94fe48f32ccf7321450a2cc07f2b724a444e5b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Nov 2013 15:19:39 +0100 Subject: genetlink: make multicast groups const, prevent abuse Register generic netlink multicast groups as an array with the family and give them contiguous group IDs. Then instead of passing the global group ID to the various functions that send messages, pass the ID relative to the family - for most families that's just 0 because the only have one group. This avoids the list_head and ID in each group, adding a new field for the mcast group ID offset to the family. At the same time, this allows us to prevent abusing groups again like the quota and dropmon code did, since we can now check that a family only uses a group it owns. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- include/linux/genl_magic_func.h | 49 +++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h index 5b9b8ae6748b..c0894dd8827b 100644 --- a/include/linux/genl_magic_func.h +++ b/include/linux/genl_magic_func.h @@ -273,49 +273,40 @@ static struct genl_family ZZZ_genl_family __read_mostly = { * Magic: define multicast groups * Magic: define multicast group registration helper */ +#define ZZZ_genl_mcgrps CONCAT_(GENL_MAGIC_FAMILY, _genl_mcgrps) +static const struct genl_multicast_group ZZZ_genl_mcgrps[] = { +#undef GENL_mc_group +#define GENL_mc_group(group) { .name = #group, }, +#include GENL_MAGIC_INCLUDE_FILE +}; + +enum CONCAT_(GENL_MAGIC_FAMILY, group_ids) { +#undef GENL_mc_group +#define GENL_mc_group(group) CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group), +#include GENL_MAGIC_INCLUDE_FILE +}; + #undef GENL_mc_group #define GENL_mc_group(group) \ -static struct genl_multicast_group \ -CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \ - .name = #group, \ -}; \ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ struct sk_buff *skb, gfp_t flags) \ { \ unsigned int group_id = \ - CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \ - if (!group_id) \ - return -EINVAL; \ + CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group); \ return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \ group_id, flags); \ } #include GENL_MAGIC_INCLUDE_FILE -int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) -{ - int err = genl_register_family_with_ops(&ZZZ_genl_family, ZZZ_genl_ops); - if (err) - return err; -#undef GENL_mc_group -#define GENL_mc_group(group) \ - err = genl_register_mc_group(&ZZZ_genl_family, \ - &CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \ - if (err) \ - goto fail; \ - else \ - pr_info("%s: mcg %s: %u\n", #group, \ - __stringify(GENL_MAGIC_FAMILY), \ - CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id); - -#include GENL_MAGIC_INCLUDE_FILE - #undef GENL_mc_group #define GENL_mc_group(group) - return 0; -fail: - genl_unregister_family(&ZZZ_genl_family); - return err; + +int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) +{ + return genl_register_family_with_ops_groups(&ZZZ_genl_family, \ + ZZZ_genl_ops, \ + ZZZ_genl_mcgrps); } void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void) -- cgit v1.2.3