Commit 494fff56 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller

ipmr, ip6mr: Make mfc_cache a common structure

mfc_cache and mfc6_cache are almost identical - the main difference is
in the origin/group addresses and comparison-key. Make a common
structure encapsulating most of the multicast routing logic  - mr_mfc
and convert both ipmr and ip6mr into using it.

For easy conversion [casting, in this case] mr_mfc has to be the first
field inside every multicast routing abstraction utilizing it.
Signed-off-by: default avatarYuval Mintz <yuvalm@mellanox.com>
Acked-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0bbbf0e7
...@@ -126,8 +126,8 @@ mlxsw_sp_mr_route_ivif_in_evifs(const struct mlxsw_sp_mr_route *mr_route) ...@@ -126,8 +126,8 @@ mlxsw_sp_mr_route_ivif_in_evifs(const struct mlxsw_sp_mr_route *mr_route)
switch (mr_route->mr_table->proto) { switch (mr_route->mr_table->proto) {
case MLXSW_SP_L3_PROTO_IPV4: case MLXSW_SP_L3_PROTO_IPV4:
ivif = mr_route->mfc4->mfc_parent; ivif = mr_route->mfc4->_c.mfc_parent;
return mr_route->mfc4->mfc_un.res.ttls[ivif] != 255; return mr_route->mfc4->_c.mfc_un.res.ttls[ivif] != 255;
case MLXSW_SP_L3_PROTO_IPV6: case MLXSW_SP_L3_PROTO_IPV6:
/* fall through */ /* fall through */
default: default:
...@@ -364,7 +364,7 @@ mlxsw_sp_mr_route4_create(struct mlxsw_sp_mr_table *mr_table, ...@@ -364,7 +364,7 @@ mlxsw_sp_mr_route4_create(struct mlxsw_sp_mr_table *mr_table,
mr_route->mfc4 = mfc; mr_route->mfc4 = mfc;
mr_route->mr_table = mr_table; mr_route->mr_table = mr_table;
for (i = 0; i < MAXVIFS; i++) { for (i = 0; i < MAXVIFS; i++) {
if (mfc->mfc_un.res.ttls[i] != 255) { if (mfc->_c.mfc_un.res.ttls[i] != 255) {
err = mlxsw_sp_mr_route_evif_link(mr_route, err = mlxsw_sp_mr_route_evif_link(mr_route,
&mr_table->vifs[i]); &mr_table->vifs[i]);
if (err) if (err)
...@@ -374,7 +374,8 @@ mlxsw_sp_mr_route4_create(struct mlxsw_sp_mr_table *mr_table, ...@@ -374,7 +374,8 @@ mlxsw_sp_mr_route4_create(struct mlxsw_sp_mr_table *mr_table,
mr_route->min_mtu = mr_table->vifs[i].dev->mtu; mr_route->min_mtu = mr_table->vifs[i].dev->mtu;
} }
} }
mlxsw_sp_mr_route_ivif_link(mr_route, &mr_table->vifs[mfc->mfc_parent]); mlxsw_sp_mr_route_ivif_link(mr_route,
&mr_table->vifs[mfc->_c.mfc_parent]);
mr_route->route_action = mlxsw_sp_mr_route_action(mr_route); mr_route->route_action = mlxsw_sp_mr_route_action(mr_route);
return mr_route; return mr_route;
...@@ -418,9 +419,9 @@ static void mlxsw_sp_mr_mfc_offload_set(struct mlxsw_sp_mr_route *mr_route, ...@@ -418,9 +419,9 @@ static void mlxsw_sp_mr_mfc_offload_set(struct mlxsw_sp_mr_route *mr_route,
switch (mr_route->mr_table->proto) { switch (mr_route->mr_table->proto) {
case MLXSW_SP_L3_PROTO_IPV4: case MLXSW_SP_L3_PROTO_IPV4:
if (offload) if (offload)
mr_route->mfc4->mfc_flags |= MFC_OFFLOAD; mr_route->mfc4->_c.mfc_flags |= MFC_OFFLOAD;
else else
mr_route->mfc4->mfc_flags &= ~MFC_OFFLOAD; mr_route->mfc4->_c.mfc_flags &= ~MFC_OFFLOAD;
break; break;
case MLXSW_SP_L3_PROTO_IPV6: case MLXSW_SP_L3_PROTO_IPV6:
/* fall through */ /* fall through */
...@@ -943,10 +944,10 @@ static void mlxsw_sp_mr_route_stats_update(struct mlxsw_sp *mlxsw_sp, ...@@ -943,10 +944,10 @@ static void mlxsw_sp_mr_route_stats_update(struct mlxsw_sp *mlxsw_sp,
switch (mr_route->mr_table->proto) { switch (mr_route->mr_table->proto) {
case MLXSW_SP_L3_PROTO_IPV4: case MLXSW_SP_L3_PROTO_IPV4:
if (mr_route->mfc4->mfc_un.res.pkt != packets) if (mr_route->mfc4->_c.mfc_un.res.pkt != packets)
mr_route->mfc4->mfc_un.res.lastuse = jiffies; mr_route->mfc4->_c.mfc_un.res.lastuse = jiffies;
mr_route->mfc4->mfc_un.res.pkt = packets; mr_route->mfc4->_c.mfc_un.res.pkt = packets;
mr_route->mfc4->mfc_un.res.bytes = bytes; mr_route->mfc4->_c.mfc_un.res.bytes = bytes;
break; break;
case MLXSW_SP_L3_PROTO_IPV6: case MLXSW_SP_L3_PROTO_IPV6:
/* fall through */ /* fall through */
......
...@@ -81,28 +81,13 @@ struct mfc_cache_cmp_arg { ...@@ -81,28 +81,13 @@ struct mfc_cache_cmp_arg {
/** /**
* struct mfc_cache - multicast routing entries * struct mfc_cache - multicast routing entries
* @mnode: rhashtable list * @_c: Common multicast routing information; has to be first [for casting]
* @mfc_mcastgrp: destination multicast group address * @mfc_mcastgrp: destination multicast group address
* @mfc_origin: source address * @mfc_origin: source address
* @cmparg: used for rhashtable comparisons * @cmparg: used for rhashtable comparisons
* @mfc_parent: source interface (iif)
* @mfc_flags: entry flags
* @expires: unresolved entry expire time
* @unresolved: unresolved cached skbs
* @last_assert: time of last assert
* @minvif: minimum VIF id
* @maxvif: maximum VIF id
* @bytes: bytes that have passed for this entry
* @pkt: packets that have passed for this entry
* @wrong_if: number of wrong source interface hits
* @lastuse: time of last use of the group (traffic or update)
* @ttls: OIF TTL threshold array
* @refcount: reference count for this entry
* @list: global entry list
* @rcu: used for entry destruction
*/ */
struct mfc_cache { struct mfc_cache {
struct rhlist_head mnode; struct mr_mfc _c;
union { union {
struct { struct {
__be32 mfc_mcastgrp; __be32 mfc_mcastgrp;
...@@ -110,28 +95,6 @@ struct mfc_cache { ...@@ -110,28 +95,6 @@ struct mfc_cache {
}; };
struct mfc_cache_cmp_arg cmparg; struct mfc_cache_cmp_arg cmparg;
}; };
vifi_t mfc_parent;
int mfc_flags;
union {
struct {
unsigned long expires;
struct sk_buff_head unresolved;
} unres;
struct {
unsigned long last_assert;
int minvif;
int maxvif;
unsigned long bytes;
unsigned long pkt;
unsigned long wrong_if;
unsigned long lastuse;
unsigned char ttls[MAXVIFS];
refcount_t refcount;
} res;
} mfc_un;
struct list_head list;
struct rcu_head rcu;
}; };
struct mfc_entry_notifier_info { struct mfc_entry_notifier_info {
...@@ -155,12 +118,12 @@ static inline void ipmr_cache_free(struct mfc_cache *mfc_cache) ...@@ -155,12 +118,12 @@ static inline void ipmr_cache_free(struct mfc_cache *mfc_cache)
static inline void ipmr_cache_put(struct mfc_cache *c) static inline void ipmr_cache_put(struct mfc_cache *c)
{ {
if (refcount_dec_and_test(&c->mfc_un.res.refcount)) if (refcount_dec_and_test(&c->_c.mfc_un.res.refcount))
ipmr_cache_free(c); ipmr_cache_free(c);
} }
static inline void ipmr_cache_hold(struct mfc_cache *c) static inline void ipmr_cache_hold(struct mfc_cache *c)
{ {
refcount_inc(&c->mfc_un.res.refcount); refcount_inc(&c->_c.mfc_un.res.refcount);
} }
#endif #endif
...@@ -71,7 +71,7 @@ struct mfc6_cache_cmp_arg { ...@@ -71,7 +71,7 @@ struct mfc6_cache_cmp_arg {
}; };
struct mfc6_cache { struct mfc6_cache {
struct rhlist_head mnode; struct mr_mfc _c;
union { union {
struct { struct {
struct in6_addr mf6c_mcastgrp; struct in6_addr mf6c_mcastgrp;
...@@ -79,27 +79,6 @@ struct mfc6_cache { ...@@ -79,27 +79,6 @@ struct mfc6_cache {
}; };
struct mfc6_cache_cmp_arg cmparg; struct mfc6_cache_cmp_arg cmparg;
}; };
mifi_t mf6c_parent; /* Source interface */
int mfc_flags; /* Flags on line */
union {
struct {
unsigned long expires;
struct sk_buff_head unresolved; /* Unresolved buffers */
} unres;
struct {
unsigned long last_assert;
int minvif;
int maxvif;
unsigned long bytes;
unsigned long pkt;
unsigned long wrong_if;
unsigned long lastuse;
unsigned char ttls[MAXMIFS]; /* TTL thresholds */
} res;
} mfc_un;
struct list_head list;
struct rcu_head rcu;
}; };
#define MFC_STATIC 1 #define MFC_STATIC 1
......
...@@ -44,6 +44,51 @@ struct vif_device { ...@@ -44,6 +44,51 @@ struct vif_device {
#define VIF_EXISTS(_mrt, _idx) (!!((_mrt)->vif_table[_idx].dev)) #define VIF_EXISTS(_mrt, _idx) (!!((_mrt)->vif_table[_idx].dev))
/**
* struct mr_mfc - common multicast routing entries
* @mnode: rhashtable list
* @mfc_parent: source interface (iif)
* @mfc_flags: entry flags
* @expires: unresolved entry expire time
* @unresolved: unresolved cached skbs
* @last_assert: time of last assert
* @minvif: minimum VIF id
* @maxvif: maximum VIF id
* @bytes: bytes that have passed for this entry
* @pkt: packets that have passed for this entry
* @wrong_if: number of wrong source interface hits
* @lastuse: time of last use of the group (traffic or update)
* @ttls: OIF TTL threshold array
* @refcount: reference count for this entry
* @list: global entry list
* @rcu: used for entry destruction
*/
struct mr_mfc {
struct rhlist_head mnode;
unsigned short mfc_parent;
int mfc_flags;
union {
struct {
unsigned long expires;
struct sk_buff_head unresolved;
} unres;
struct {
unsigned long last_assert;
int minvif;
int maxvif;
unsigned long bytes;
unsigned long pkt;
unsigned long wrong_if;
unsigned long lastuse;
unsigned char ttls[MAXVIFS];
refcount_t refcount;
} res;
} mfc_un;
struct list_head list;
struct rcu_head rcu;
};
/** /**
* struct mr_table - a multicast routing table * struct mr_table - a multicast routing table
* @list: entry within a list of multicast routing tables * @list: entry within a list of multicast routing tables
......
...@@ -106,7 +106,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -106,7 +106,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
static int ipmr_cache_report(struct mr_table *mrt, static int ipmr_cache_report(struct mr_table *mrt,
struct sk_buff *pkt, vifi_t vifi, int assert); struct sk_buff *pkt, vifi_t vifi, int assert);
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
struct mfc_cache *c, struct rtmsg *rtm); struct mr_mfc *c, struct rtmsg *rtm);
static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc, static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
int cmd); int cmd);
static void igmpmsg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt); static void igmpmsg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
...@@ -343,7 +343,7 @@ static inline int ipmr_hash_cmp(struct rhashtable_compare_arg *arg, ...@@ -343,7 +343,7 @@ static inline int ipmr_hash_cmp(struct rhashtable_compare_arg *arg,
} }
static const struct rhashtable_params ipmr_rht_params = { static const struct rhashtable_params ipmr_rht_params = {
.head_offset = offsetof(struct mfc_cache, mnode), .head_offset = offsetof(struct mr_mfc, mnode),
.key_offset = offsetof(struct mfc_cache, cmparg), .key_offset = offsetof(struct mfc_cache, cmparg),
.key_len = sizeof(struct mfc_cache_cmp_arg), .key_len = sizeof(struct mfc_cache_cmp_arg),
.nelem_hint = 3, .nelem_hint = 3,
...@@ -752,14 +752,14 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify, ...@@ -752,14 +752,14 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
static void ipmr_cache_free_rcu(struct rcu_head *head) static void ipmr_cache_free_rcu(struct rcu_head *head)
{ {
struct mfc_cache *c = container_of(head, struct mfc_cache, rcu); struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
kmem_cache_free(mrt_cachep, c); kmem_cache_free(mrt_cachep, (struct mfc_cache *)c);
} }
void ipmr_cache_free(struct mfc_cache *c) void ipmr_cache_free(struct mfc_cache *c)
{ {
call_rcu(&c->rcu, ipmr_cache_free_rcu); call_rcu(&c->_c.rcu, ipmr_cache_free_rcu);
} }
EXPORT_SYMBOL(ipmr_cache_free); EXPORT_SYMBOL(ipmr_cache_free);
...@@ -774,7 +774,7 @@ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c) ...@@ -774,7 +774,7 @@ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c)
atomic_dec(&mrt->cache_resolve_queue_len); atomic_dec(&mrt->cache_resolve_queue_len);
while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved))) {
if (ip_hdr(skb)->version == 0) { if (ip_hdr(skb)->version == 0) {
struct nlmsghdr *nlh = skb_pull(skb, struct nlmsghdr *nlh = skb_pull(skb,
sizeof(struct iphdr)); sizeof(struct iphdr));
...@@ -798,9 +798,9 @@ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c) ...@@ -798,9 +798,9 @@ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c)
static void ipmr_expire_process(struct timer_list *t) static void ipmr_expire_process(struct timer_list *t)
{ {
struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer); struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
unsigned long now; struct mr_mfc *c, *next;
unsigned long expires; unsigned long expires;
struct mfc_cache *c, *next; unsigned long now;
if (!spin_trylock(&mfc_unres_lock)) { if (!spin_trylock(&mfc_unres_lock)) {
mod_timer(&mrt->ipmr_expire_timer, jiffies+HZ/10); mod_timer(&mrt->ipmr_expire_timer, jiffies+HZ/10);
...@@ -822,8 +822,8 @@ static void ipmr_expire_process(struct timer_list *t) ...@@ -822,8 +822,8 @@ static void ipmr_expire_process(struct timer_list *t)
} }
list_del(&c->list); list_del(&c->list);
mroute_netlink_event(mrt, c, RTM_DELROUTE); mroute_netlink_event(mrt, (struct mfc_cache *)c, RTM_DELROUTE);
ipmr_destroy_unres(mrt, c); ipmr_destroy_unres(mrt, (struct mfc_cache *)c);
} }
if (!list_empty(&mrt->mfc_unres_queue)) if (!list_empty(&mrt->mfc_unres_queue))
...@@ -834,7 +834,7 @@ static void ipmr_expire_process(struct timer_list *t) ...@@ -834,7 +834,7 @@ static void ipmr_expire_process(struct timer_list *t)
} }
/* Fill oifs list. It is called under write locked mrt_lock. */ /* Fill oifs list. It is called under write locked mrt_lock. */
static void ipmr_update_thresholds(struct mr_table *mrt, struct mfc_cache *cache, static void ipmr_update_thresholds(struct mr_table *mrt, struct mr_mfc *cache,
unsigned char *ttls) unsigned char *ttls)
{ {
int vifi; int vifi;
...@@ -974,11 +974,11 @@ static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt, ...@@ -974,11 +974,11 @@ static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt,
.mfc_origin = origin .mfc_origin = origin
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc_cache *c; struct mr_mfc *c;
list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) rhl_for_each_entry_rcu(c, tmp, list, mnode)
return c; return (struct mfc_cache *)c;
return NULL; return NULL;
} }
...@@ -992,12 +992,12 @@ static struct mfc_cache *ipmr_cache_find_any_parent(struct mr_table *mrt, ...@@ -992,12 +992,12 @@ static struct mfc_cache *ipmr_cache_find_any_parent(struct mr_table *mrt,
.mfc_origin = htonl(INADDR_ANY) .mfc_origin = htonl(INADDR_ANY)
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc_cache *c; struct mr_mfc *c;
list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) rhl_for_each_entry_rcu(c, tmp, list, mnode)
if (c->mfc_un.res.ttls[vifi] < 255) if (c->mfc_un.res.ttls[vifi] < 255)
return c; return (struct mfc_cache *)c;
return NULL; return NULL;
} }
...@@ -1011,20 +1011,22 @@ static struct mfc_cache *ipmr_cache_find_any(struct mr_table *mrt, ...@@ -1011,20 +1011,22 @@ static struct mfc_cache *ipmr_cache_find_any(struct mr_table *mrt,
.mfc_origin = htonl(INADDR_ANY) .mfc_origin = htonl(INADDR_ANY)
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc_cache *c, *proxy; struct mr_mfc *c;
if (mcastgrp == htonl(INADDR_ANY)) if (mcastgrp == htonl(INADDR_ANY))
goto skip; goto skip;
list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) { rhl_for_each_entry_rcu(c, tmp, list, mnode) {
struct mfc_cache *proxy;
if (c->mfc_un.res.ttls[vifi] < 255) if (c->mfc_un.res.ttls[vifi] < 255)
return c; return (struct mfc_cache *)c;
/* It's ok if the vifi is part of the static tree */ /* It's ok if the vifi is part of the static tree */
proxy = ipmr_cache_find_any_parent(mrt, c->mfc_parent); proxy = ipmr_cache_find_any_parent(mrt, c->mfc_parent);
if (proxy && proxy->mfc_un.res.ttls[vifi] < 255) if (proxy && proxy->_c.mfc_un.res.ttls[vifi] < 255)
return c; return (struct mfc_cache *)c;
} }
skip: skip:
...@@ -1041,12 +1043,12 @@ static struct mfc_cache *ipmr_cache_find_parent(struct mr_table *mrt, ...@@ -1041,12 +1043,12 @@ static struct mfc_cache *ipmr_cache_find_parent(struct mr_table *mrt,
.mfc_origin = origin, .mfc_origin = origin,
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc_cache *c; struct mr_mfc *c;
list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ipmr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) rhl_for_each_entry_rcu(c, tmp, list, mnode)
if (parent == -1 || parent == c->mfc_parent) if (parent == -1 || parent == c->mfc_parent)
return c; return (struct mfc_cache *)c;
return NULL; return NULL;
} }
...@@ -1057,9 +1059,9 @@ static struct mfc_cache *ipmr_cache_alloc(void) ...@@ -1057,9 +1059,9 @@ static struct mfc_cache *ipmr_cache_alloc(void)
struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
if (c) { if (c) {
c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
c->mfc_un.res.minvif = MAXVIFS; c->_c.mfc_un.res.minvif = MAXVIFS;
refcount_set(&c->mfc_un.res.refcount, 1); refcount_set(&c->_c.mfc_un.res.refcount, 1);
} }
return c; return c;
} }
...@@ -1069,8 +1071,8 @@ static struct mfc_cache *ipmr_cache_alloc_unres(void) ...@@ -1069,8 +1071,8 @@ static struct mfc_cache *ipmr_cache_alloc_unres(void)
struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
if (c) { if (c) {
skb_queue_head_init(&c->mfc_un.unres.unresolved); skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
c->mfc_un.unres.expires = jiffies + 10*HZ; c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
} }
return c; return c;
} }
...@@ -1083,12 +1085,13 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, ...@@ -1083,12 +1085,13 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
struct nlmsgerr *e; struct nlmsgerr *e;
/* Play the pending entries through our router */ /* Play the pending entries through our router */
while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
if (ip_hdr(skb)->version == 0) { if (ip_hdr(skb)->version == 0) {
struct nlmsghdr *nlh = skb_pull(skb, struct nlmsghdr *nlh = skb_pull(skb,
sizeof(struct iphdr)); sizeof(struct iphdr));
if (__ipmr_fill_mroute(mrt, skb, c, nlmsg_data(nlh)) > 0) { if (__ipmr_fill_mroute(mrt, skb, &c->_c,
nlmsg_data(nlh)) > 0) {
nlh->nlmsg_len = skb_tail_pointer(skb) - nlh->nlmsg_len = skb_tail_pointer(skb) -
(u8 *)nlh; (u8 *)nlh;
} else { } else {
...@@ -1196,7 +1199,7 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, ...@@ -1196,7 +1199,7 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi,
int err; int err;
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
list_for_each_entry(c, &mrt->mfc_unres_queue, list) { list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
if (c->mfc_mcastgrp == iph->daddr && if (c->mfc_mcastgrp == iph->daddr &&
c->mfc_origin == iph->saddr) { c->mfc_origin == iph->saddr) {
found = true; found = true;
...@@ -1215,12 +1218,13 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, ...@@ -1215,12 +1218,13 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi,
} }
/* Fill in the new cache entry */ /* Fill in the new cache entry */
c->mfc_parent = -1; c->_c.mfc_parent = -1;
c->mfc_origin = iph->saddr; c->mfc_origin = iph->saddr;
c->mfc_mcastgrp = iph->daddr; c->mfc_mcastgrp = iph->daddr;
/* Reflect first query at mrouted. */ /* Reflect first query at mrouted. */
err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE); err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE);
if (err < 0) { if (err < 0) {
/* If the report failed throw the cache entry /* If the report failed throw the cache entry
out - Brad Parker out - Brad Parker
...@@ -1233,15 +1237,16 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, ...@@ -1233,15 +1237,16 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi,
} }
atomic_inc(&mrt->cache_resolve_queue_len); atomic_inc(&mrt->cache_resolve_queue_len);
list_add(&c->list, &mrt->mfc_unres_queue); list_add(&c->_c.list, &mrt->mfc_unres_queue);
mroute_netlink_event(mrt, c, RTM_NEWROUTE); mroute_netlink_event(mrt, c, RTM_NEWROUTE);
if (atomic_read(&mrt->cache_resolve_queue_len) == 1) if (atomic_read(&mrt->cache_resolve_queue_len) == 1)
mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires); mod_timer(&mrt->ipmr_expire_timer,
c->_c.mfc_un.unres.expires);
} }
/* See if we can append the packet */ /* See if we can append the packet */
if (c->mfc_un.unres.unresolved.qlen > 3) { if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
kfree_skb(skb); kfree_skb(skb);
err = -ENOBUFS; err = -ENOBUFS;
} else { } else {
...@@ -1249,7 +1254,7 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, ...@@ -1249,7 +1254,7 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi,
skb->dev = dev; skb->dev = dev;
skb->skb_iif = dev->ifindex; skb->skb_iif = dev->ifindex;
} }
skb_queue_tail(&c->mfc_un.unres.unresolved, skb); skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
err = 0; err = 0;
} }
...@@ -1271,8 +1276,8 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc, int parent) ...@@ -1271,8 +1276,8 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc, int parent)
rcu_read_unlock(); rcu_read_unlock();
if (!c) if (!c)
return -ENOENT; return -ENOENT;
rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params); rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ipmr_rht_params);
list_del_rcu(&c->list); list_del_rcu(&c->_c.list);
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, c, mrt->id); call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, c, mrt->id);
mroute_netlink_event(mrt, c, RTM_DELROUTE); mroute_netlink_event(mrt, c, RTM_DELROUTE);
ipmr_cache_put(c); ipmr_cache_put(c);
...@@ -1284,6 +1289,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1284,6 +1289,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
struct mfcctl *mfc, int mrtsock, int parent) struct mfcctl *mfc, int mrtsock, int parent)
{ {
struct mfc_cache *uc, *c; struct mfc_cache *uc, *c;
struct mr_mfc *_uc;
bool found; bool found;
int ret; int ret;
...@@ -1297,10 +1303,10 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1297,10 +1303,10 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
rcu_read_unlock(); rcu_read_unlock();
if (c) { if (c) {
write_lock_bh(&mrt_lock); write_lock_bh(&mrt_lock);
c->mfc_parent = mfc->mfcc_parent; c->_c.mfc_parent = mfc->mfcc_parent;
ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls); ipmr_update_thresholds(mrt, &c->_c, mfc->mfcc_ttls);
if (!mrtsock) if (!mrtsock)
c->mfc_flags |= MFC_STATIC; c->_c.mfc_flags |= MFC_STATIC;
write_unlock_bh(&mrt_lock); write_unlock_bh(&mrt_lock);
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE, c, call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE, c,
mrt->id); mrt->id);
...@@ -1318,28 +1324,29 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1318,28 +1324,29 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
c->mfc_origin = mfc->mfcc_origin.s_addr; c->mfc_origin = mfc->mfcc_origin.s_addr;
c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr; c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr;
c->mfc_parent = mfc->mfcc_parent; c->_c.mfc_parent = mfc->mfcc_parent;
ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls); ipmr_update_thresholds(mrt, &c->_c, mfc->mfcc_ttls);
if (!mrtsock) if (!mrtsock)
c->mfc_flags |= MFC_STATIC; c->_c.mfc_flags |= MFC_STATIC;
ret = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->mnode, ret = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
ipmr_rht_params); ipmr_rht_params);
if (ret) { if (ret) {
pr_err("ipmr: rhtable insert error %d\n", ret); pr_err("ipmr: rhtable insert error %d\n", ret);
ipmr_cache_free(c); ipmr_cache_free(c);
return ret; return ret;
} }
list_add_tail_rcu(&c->list, &mrt->mfc_cache_list); list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
/* Check to see if we resolved a queued list. If so we /* Check to see if we resolved a queued list. If so we
* need to send on the frames and tidy up. * need to send on the frames and tidy up.
*/ */
found = false; found = false;
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
list_for_each_entry(uc, &mrt->mfc_unres_queue, list) { list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
uc = (struct mfc_cache *)_uc;
if (uc->mfc_origin == c->mfc_origin && if (uc->mfc_origin == c->mfc_origin &&
uc->mfc_mcastgrp == c->mfc_mcastgrp) { uc->mfc_mcastgrp == c->mfc_mcastgrp) {
list_del(&uc->list); list_del(&_uc->list);
atomic_dec(&mrt->cache_resolve_queue_len); atomic_dec(&mrt->cache_resolve_queue_len);
found = true; found = true;
break; break;
...@@ -1362,7 +1369,8 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1362,7 +1369,8 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
static void mroute_clean_tables(struct mr_table *mrt, bool all) static void mroute_clean_tables(struct mr_table *mrt, bool all)
{ {
struct net *net = read_pnet(&mrt->net); struct net *net = read_pnet(&mrt->net);
struct mfc_cache *c, *tmp; struct mr_mfc *c, *tmp;
struct mfc_cache *cache;
LIST_HEAD(list); LIST_HEAD(list);
int i; int i;
...@@ -1380,18 +1388,20 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all) ...@@ -1380,18 +1388,20 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
continue; continue;
rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params); rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
list_del_rcu(&c->list); list_del_rcu(&c->list);
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, c, cache = (struct mfc_cache *)c;
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
mrt->id); mrt->id);
mroute_netlink_event(mrt, c, RTM_DELROUTE); mroute_netlink_event(mrt, cache, RTM_DELROUTE);
ipmr_cache_put(c); ipmr_cache_put(cache);
} }
if (atomic_read(&mrt->cache_resolve_queue_len) != 0) { if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) { list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
list_del(&c->list); list_del(&c->list);
mroute_netlink_event(mrt, c, RTM_DELROUTE); cache = (struct mfc_cache *)c;
ipmr_destroy_unres(mrt, c); mroute_netlink_event(mrt, cache, RTM_DELROUTE);
ipmr_destroy_unres(mrt, cache);
} }
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
} }
...@@ -1683,9 +1693,9 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) ...@@ -1683,9 +1693,9 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
rcu_read_lock(); rcu_read_lock();
c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr); c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
if (c) { if (c) {
sr.pktcnt = c->mfc_un.res.pkt; sr.pktcnt = c->_c.mfc_un.res.pkt;
sr.bytecnt = c->mfc_un.res.bytes; sr.bytecnt = c->_c.mfc_un.res.bytes;
sr.wrong_if = c->mfc_un.res.wrong_if; sr.wrong_if = c->_c.mfc_un.res.wrong_if;
rcu_read_unlock(); rcu_read_unlock();
if (copy_to_user(arg, &sr, sizeof(sr))) if (copy_to_user(arg, &sr, sizeof(sr)))
...@@ -1757,9 +1767,9 @@ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) ...@@ -1757,9 +1767,9 @@ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
rcu_read_lock(); rcu_read_lock();
c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr); c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
if (c) { if (c) {
sr.pktcnt = c->mfc_un.res.pkt; sr.pktcnt = c->_c.mfc_un.res.pkt;
sr.bytecnt = c->mfc_un.res.bytes; sr.bytecnt = c->_c.mfc_un.res.bytes;
sr.wrong_if = c->mfc_un.res.wrong_if; sr.wrong_if = c->_c.mfc_un.res.wrong_if;
rcu_read_unlock(); rcu_read_unlock();
if (copy_to_user(arg, &sr, sizeof(sr))) if (copy_to_user(arg, &sr, sizeof(sr)))
...@@ -1983,18 +1993,18 @@ static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev) ...@@ -1983,18 +1993,18 @@ static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev)
/* "local" means that we should preserve one skb (for local delivery) */ /* "local" means that we should preserve one skb (for local delivery) */
static void ip_mr_forward(struct net *net, struct mr_table *mrt, static void ip_mr_forward(struct net *net, struct mr_table *mrt,
struct net_device *dev, struct sk_buff *skb, struct net_device *dev, struct sk_buff *skb,
struct mfc_cache *cache, int local) struct mfc_cache *c, int local)
{ {
int true_vifi = ipmr_find_vif(mrt, dev); int true_vifi = ipmr_find_vif(mrt, dev);
int psend = -1; int psend = -1;
int vif, ct; int vif, ct;
vif = cache->mfc_parent; vif = c->_c.mfc_parent;
cache->mfc_un.res.pkt++; c->_c.mfc_un.res.pkt++;
cache->mfc_un.res.bytes += skb->len; c->_c.mfc_un.res.bytes += skb->len;
cache->mfc_un.res.lastuse = jiffies; c->_c.mfc_un.res.lastuse = jiffies;
if (cache->mfc_origin == htonl(INADDR_ANY) && true_vifi >= 0) { if (c->mfc_origin == htonl(INADDR_ANY) && true_vifi >= 0) {
struct mfc_cache *cache_proxy; struct mfc_cache *cache_proxy;
/* For an (*,G) entry, we only check that the incomming /* For an (*,G) entry, we only check that the incomming
...@@ -2002,7 +2012,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2002,7 +2012,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
*/ */
cache_proxy = ipmr_cache_find_any_parent(mrt, vif); cache_proxy = ipmr_cache_find_any_parent(mrt, vif);
if (cache_proxy && if (cache_proxy &&
cache_proxy->mfc_un.res.ttls[true_vifi] < 255) cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255)
goto forward; goto forward;
} }
...@@ -2023,7 +2033,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2023,7 +2033,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
goto dont_forward; goto dont_forward;
} }
cache->mfc_un.res.wrong_if++; c->_c.mfc_un.res.wrong_if++;
if (true_vifi >= 0 && mrt->mroute_do_assert && if (true_vifi >= 0 && mrt->mroute_do_assert &&
/* pimsm uses asserts, when switching from RPT to SPT, /* pimsm uses asserts, when switching from RPT to SPT,
...@@ -2032,10 +2042,11 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2032,10 +2042,11 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
* large chunk of pimd to kernel. Ough... --ANK * large chunk of pimd to kernel. Ough... --ANK
*/ */
(mrt->mroute_do_pim || (mrt->mroute_do_pim ||
cache->mfc_un.res.ttls[true_vifi] < 255) && c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
time_after(jiffies, time_after(jiffies,
cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { c->_c.mfc_un.res.last_assert +
cache->mfc_un.res.last_assert = jiffies; MFC_ASSERT_THRESH)) {
c->_c.mfc_un.res.last_assert = jiffies;
ipmr_cache_report(mrt, skb, true_vifi, IGMPMSG_WRONGVIF); ipmr_cache_report(mrt, skb, true_vifi, IGMPMSG_WRONGVIF);
} }
goto dont_forward; goto dont_forward;
...@@ -2046,33 +2057,33 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2046,33 +2057,33 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
mrt->vif_table[vif].bytes_in += skb->len; mrt->vif_table[vif].bytes_in += skb->len;
/* Forward the frame */ /* Forward the frame */
if (cache->mfc_origin == htonl(INADDR_ANY) && if (c->mfc_origin == htonl(INADDR_ANY) &&
cache->mfc_mcastgrp == htonl(INADDR_ANY)) { c->mfc_mcastgrp == htonl(INADDR_ANY)) {
if (true_vifi >= 0 && if (true_vifi >= 0 &&
true_vifi != cache->mfc_parent && true_vifi != c->_c.mfc_parent &&
ip_hdr(skb)->ttl > ip_hdr(skb)->ttl >
cache->mfc_un.res.ttls[cache->mfc_parent]) { c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
/* It's an (*,*) entry and the packet is not coming from /* It's an (*,*) entry and the packet is not coming from
* the upstream: forward the packet to the upstream * the upstream: forward the packet to the upstream
* only. * only.
*/ */
psend = cache->mfc_parent; psend = c->_c.mfc_parent;
goto last_forward; goto last_forward;
} }
goto dont_forward; goto dont_forward;
} }
for (ct = cache->mfc_un.res.maxvif - 1; for (ct = c->_c.mfc_un.res.maxvif - 1;
ct >= cache->mfc_un.res.minvif; ct--) { ct >= c->_c.mfc_un.res.minvif; ct--) {
/* For (*,G) entry, don't forward to the incoming interface */ /* For (*,G) entry, don't forward to the incoming interface */
if ((cache->mfc_origin != htonl(INADDR_ANY) || if ((c->mfc_origin != htonl(INADDR_ANY) ||
ct != true_vifi) && ct != true_vifi) &&
ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) { ip_hdr(skb)->ttl > c->_c.mfc_un.res.ttls[ct]) {
if (psend != -1) { if (psend != -1) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2) if (skb2)
ipmr_queue_xmit(net, mrt, true_vifi, ipmr_queue_xmit(net, mrt, true_vifi,
skb2, cache, psend); skb2, c, psend);
} }
psend = ct; psend = ct;
} }
...@@ -2084,9 +2095,9 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2084,9 +2095,9 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
if (skb2) if (skb2)
ipmr_queue_xmit(net, mrt, true_vifi, skb2, ipmr_queue_xmit(net, mrt, true_vifi, skb2,
cache, psend); c, psend);
} else { } else {
ipmr_queue_xmit(net, mrt, true_vifi, skb, cache, psend); ipmr_queue_xmit(net, mrt, true_vifi, skb, c, psend);
return; return;
} }
} }
...@@ -2285,7 +2296,7 @@ static int pim_rcv(struct sk_buff *skb) ...@@ -2285,7 +2296,7 @@ static int pim_rcv(struct sk_buff *skb)
#endif #endif
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
struct mfc_cache *c, struct rtmsg *rtm) struct mr_mfc *c, struct rtmsg *rtm)
{ {
struct rta_mfc_stats mfcs; struct rta_mfc_stats mfcs;
struct nlattr *mp_attr; struct nlattr *mp_attr;
...@@ -2401,7 +2412,7 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, ...@@ -2401,7 +2412,7 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
} }
read_lock(&mrt_lock); read_lock(&mrt_lock);
err = __ipmr_fill_mroute(mrt, skb, cache, rtm); err = __ipmr_fill_mroute(mrt, skb, &cache->_c, rtm);
read_unlock(&mrt_lock); read_unlock(&mrt_lock);
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
...@@ -2429,7 +2440,7 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, ...@@ -2429,7 +2440,7 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
goto nla_put_failure; goto nla_put_failure;
rtm->rtm_type = RTN_MULTICAST; rtm->rtm_type = RTN_MULTICAST;
rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_scope = RT_SCOPE_UNIVERSE;
if (c->mfc_flags & MFC_STATIC) if (c->_c.mfc_flags & MFC_STATIC)
rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_protocol = RTPROT_STATIC;
else else
rtm->rtm_protocol = RTPROT_MROUTED; rtm->rtm_protocol = RTPROT_MROUTED;
...@@ -2438,7 +2449,7 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, ...@@ -2438,7 +2449,7 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
if (nla_put_in_addr(skb, RTA_SRC, c->mfc_origin) || if (nla_put_in_addr(skb, RTA_SRC, c->mfc_origin) ||
nla_put_in_addr(skb, RTA_DST, c->mfc_mcastgrp)) nla_put_in_addr(skb, RTA_DST, c->mfc_mcastgrp))
goto nla_put_failure; goto nla_put_failure;
err = __ipmr_fill_mroute(mrt, skb, c, rtm); err = __ipmr_fill_mroute(mrt, skb, &c->_c, rtm);
/* do not break the dump if cache is unresolved */ /* do not break the dump if cache is unresolved */
if (err < 0 && err != -ENOENT) if (err < 0 && err != -ENOENT)
goto nla_put_failure; goto nla_put_failure;
...@@ -2479,7 +2490,8 @@ static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc, ...@@ -2479,7 +2490,8 @@ static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
struct sk_buff *skb; struct sk_buff *skb;
int err = -ENOBUFS; int err = -ENOBUFS;
skb = nlmsg_new(mroute_msgsize(mfc->mfc_parent >= MAXVIFS, mrt->maxvif), skb = nlmsg_new(mroute_msgsize(mfc->_c.mfc_parent >= MAXVIFS,
mrt->maxvif),
GFP_ATOMIC); GFP_ATOMIC);
if (!skb) if (!skb)
goto errout; goto errout;
...@@ -2624,10 +2636,10 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, ...@@ -2624,10 +2636,10 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct mr_table *mrt;
struct mfc_cache *mfc;
unsigned int t = 0, s_t; unsigned int t = 0, s_t;
unsigned int e = 0, s_e; unsigned int e = 0, s_e;
struct mr_table *mrt;
struct mr_mfc *mfc;
s_t = cb->args[0]; s_t = cb->args[0];
s_e = cb->args[1]; s_e = cb->args[1];
...@@ -2642,8 +2654,8 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2642,8 +2654,8 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
if (ipmr_fill_mroute(mrt, skb, if (ipmr_fill_mroute(mrt, skb,
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
mfc, RTM_NEWROUTE, (struct mfc_cache *)mfc,
NLM_F_MULTI) < 0) RTM_NEWROUTE, NLM_F_MULTI) < 0)
goto done; goto done;
next_entry: next_entry:
e++; e++;
...@@ -2658,8 +2670,8 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2658,8 +2670,8 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
if (ipmr_fill_mroute(mrt, skb, if (ipmr_fill_mroute(mrt, skb,
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
mfc, RTM_NEWROUTE, (struct mfc_cache *)mfc,
NLM_F_MULTI) < 0) { RTM_NEWROUTE, NLM_F_MULTI) < 0) {
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
goto done; goto done;
} }
...@@ -3051,20 +3063,21 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net, ...@@ -3051,20 +3063,21 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net,
struct ipmr_mfc_iter *it, loff_t pos) struct ipmr_mfc_iter *it, loff_t pos)
{ {
struct mr_table *mrt = it->mrt; struct mr_table *mrt = it->mrt;
struct mfc_cache *mfc; struct mr_mfc *mfc;
rcu_read_lock(); rcu_read_lock();
it->cache = &mrt->mfc_cache_list; it->cache = &mrt->mfc_cache_list;
list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list) list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list)
if (pos-- == 0) if (pos-- == 0)
return mfc; return (struct mfc_cache *)mfc;
rcu_read_unlock(); rcu_read_unlock();
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
it->cache = &mrt->mfc_unres_queue; it->cache = &mrt->mfc_unres_queue;
list_for_each_entry(mfc, it->cache, list) list_for_each_entry(mfc, it->cache, list)
if (pos-- == 0) if (pos-- == 0)
return mfc; return (struct mfc_cache *)mfc;
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
it->cache = NULL; it->cache = NULL;
...@@ -3100,8 +3113,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -3100,8 +3113,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
if (v == SEQ_START_TOKEN) if (v == SEQ_START_TOKEN)
return ipmr_mfc_seq_idx(net, seq->private, 0); return ipmr_mfc_seq_idx(net, seq->private, 0);
if (mfc->list.next != it->cache) if (mfc->_c.list.next != it->cache)
return list_entry(mfc->list.next, struct mfc_cache, list); return (struct mfc_cache *)(list_entry(mfc->_c.list.next,
struct mr_mfc, list));
if (it->cache == &mrt->mfc_unres_queue) if (it->cache == &mrt->mfc_unres_queue)
goto end_of_list; goto end_of_list;
...@@ -3112,7 +3126,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -3112,7 +3126,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
if (!list_empty(it->cache)) if (!list_empty(it->cache))
return list_first_entry(it->cache, struct mfc_cache, list); return (struct mfc_cache *)(list_first_entry(it->cache,
struct mr_mfc,
list));
end_of_list: end_of_list:
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
...@@ -3147,20 +3163,20 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) ...@@ -3147,20 +3163,20 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%08X %08X %-3hd", seq_printf(seq, "%08X %08X %-3hd",
(__force u32) mfc->mfc_mcastgrp, (__force u32) mfc->mfc_mcastgrp,
(__force u32) mfc->mfc_origin, (__force u32) mfc->mfc_origin,
mfc->mfc_parent); mfc->_c.mfc_parent);
if (it->cache != &mrt->mfc_unres_queue) { if (it->cache != &mrt->mfc_unres_queue) {
seq_printf(seq, " %8lu %8lu %8lu", seq_printf(seq, " %8lu %8lu %8lu",
mfc->mfc_un.res.pkt, mfc->_c.mfc_un.res.pkt,
mfc->mfc_un.res.bytes, mfc->_c.mfc_un.res.bytes,
mfc->mfc_un.res.wrong_if); mfc->_c.mfc_un.res.wrong_if);
for (n = mfc->mfc_un.res.minvif; for (n = mfc->_c.mfc_un.res.minvif;
n < mfc->mfc_un.res.maxvif; n++) { n < mfc->_c.mfc_un.res.maxvif; n++) {
if (VIF_EXISTS(mrt, n) && if (VIF_EXISTS(mrt, n) &&
mfc->mfc_un.res.ttls[n] < 255) mfc->_c.mfc_un.res.ttls[n] < 255)
seq_printf(seq, seq_printf(seq,
" %2d:%-3d", " %2d:%-3d",
n, mfc->mfc_un.res.ttls[n]); n, mfc->_c.mfc_un.res.ttls[n]);
} }
} else { } else {
/* unresolved mfc_caches don't contain /* unresolved mfc_caches don't contain
...@@ -3219,7 +3235,7 @@ static int ipmr_dump(struct net *net, struct notifier_block *nb) ...@@ -3219,7 +3235,7 @@ static int ipmr_dump(struct net *net, struct notifier_block *nb)
ipmr_for_each_table(mrt, net) { ipmr_for_each_table(mrt, net) {
struct vif_device *v = &mrt->vif_table[0]; struct vif_device *v = &mrt->vif_table[0];
struct mfc_cache *mfc; struct mr_mfc *mfc;
int vifi; int vifi;
/* Notifiy on table VIF entries */ /* Notifiy on table VIF entries */
...@@ -3236,7 +3252,8 @@ static int ipmr_dump(struct net *net, struct notifier_block *nb) ...@@ -3236,7 +3252,8 @@ static int ipmr_dump(struct net *net, struct notifier_block *nb)
/* Notify on table MFC entries */ /* Notify on table MFC entries */
list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list) list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list)
call_ipmr_mfc_entry_notifier(nb, net, call_ipmr_mfc_entry_notifier(nb, net,
FIB_EVENT_ENTRY_ADD, mfc, FIB_EVENT_ENTRY_ADD,
(struct mfc_cache *)mfc,
mrt->id); mrt->id);
} }
......
...@@ -285,7 +285,7 @@ static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg, ...@@ -285,7 +285,7 @@ static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg,
} }
static const struct rhashtable_params ip6mr_rht_params = { static const struct rhashtable_params ip6mr_rht_params = {
.head_offset = offsetof(struct mfc6_cache, mnode), .head_offset = offsetof(struct mr_mfc, mnode),
.key_offset = offsetof(struct mfc6_cache, cmparg), .key_offset = offsetof(struct mfc6_cache, cmparg),
.key_len = sizeof(struct mfc6_cache_cmp_arg), .key_len = sizeof(struct mfc6_cache_cmp_arg),
.nelem_hint = 3, .nelem_hint = 3,
...@@ -335,20 +335,20 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, ...@@ -335,20 +335,20 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net,
struct ipmr_mfc_iter *it, loff_t pos) struct ipmr_mfc_iter *it, loff_t pos)
{ {
struct mr_table *mrt = it->mrt; struct mr_table *mrt = it->mrt;
struct mfc6_cache *mfc; struct mr_mfc *mfc;
rcu_read_lock(); rcu_read_lock();
it->cache = &mrt->mfc_cache_list; it->cache = &mrt->mfc_cache_list;
list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list) list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list)
if (pos-- == 0) if (pos-- == 0)
return mfc; return (struct mfc6_cache *)mfc;
rcu_read_unlock(); rcu_read_unlock();
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
it->cache = &mrt->mfc_unres_queue; it->cache = &mrt->mfc_unres_queue;
list_for_each_entry(mfc, it->cache, list) list_for_each_entry(mfc, it->cache, list)
if (pos-- == 0) if (pos-- == 0)
return mfc; return (struct mfc6_cache *)mfc;
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
it->cache = NULL; it->cache = NULL;
...@@ -492,8 +492,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -492,8 +492,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
if (v == SEQ_START_TOKEN) if (v == SEQ_START_TOKEN)
return ipmr_mfc_seq_idx(net, seq->private, 0); return ipmr_mfc_seq_idx(net, seq->private, 0);
if (mfc->list.next != it->cache) if (mfc->_c.list.next != it->cache)
return list_entry(mfc->list.next, struct mfc6_cache, list); return (struct mfc6_cache *)(list_entry(mfc->_c.list.next,
struct mr_mfc, list));
if (it->cache == &mrt->mfc_unres_queue) if (it->cache == &mrt->mfc_unres_queue)
goto end_of_list; goto end_of_list;
...@@ -504,7 +505,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -504,7 +505,9 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
if (!list_empty(it->cache)) if (!list_empty(it->cache))
return list_first_entry(it->cache, struct mfc6_cache, list); return (struct mfc6_cache *)(list_first_entry(it->cache,
struct mr_mfc,
list));
end_of_list: end_of_list:
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
...@@ -540,20 +543,20 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) ...@@ -540,20 +543,20 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%pI6 %pI6 %-3hd", seq_printf(seq, "%pI6 %pI6 %-3hd",
&mfc->mf6c_mcastgrp, &mfc->mf6c_origin, &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
mfc->mf6c_parent); mfc->_c.mfc_parent);
if (it->cache != &mrt->mfc_unres_queue) { if (it->cache != &mrt->mfc_unres_queue) {
seq_printf(seq, " %8lu %8lu %8lu", seq_printf(seq, " %8lu %8lu %8lu",
mfc->mfc_un.res.pkt, mfc->_c.mfc_un.res.pkt,
mfc->mfc_un.res.bytes, mfc->_c.mfc_un.res.bytes,
mfc->mfc_un.res.wrong_if); mfc->_c.mfc_un.res.wrong_if);
for (n = mfc->mfc_un.res.minvif; for (n = mfc->_c.mfc_un.res.minvif;
n < mfc->mfc_un.res.maxvif; n++) { n < mfc->_c.mfc_un.res.maxvif; n++) {
if (VIF_EXISTS(mrt, n) && if (VIF_EXISTS(mrt, n) &&
mfc->mfc_un.res.ttls[n] < 255) mfc->_c.mfc_un.res.ttls[n] < 255)
seq_printf(seq, seq_printf(seq,
" %2d:%-3d", " %2d:%-3d", n,
n, mfc->mfc_un.res.ttls[n]); mfc->_c.mfc_un.res.ttls[n]);
} }
} else { } else {
/* unresolved mfc_caches don't contain /* unresolved mfc_caches don't contain
...@@ -800,14 +803,14 @@ static int mif6_delete(struct mr_table *mrt, int vifi, int notify, ...@@ -800,14 +803,14 @@ static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
static inline void ip6mr_cache_free_rcu(struct rcu_head *head) static inline void ip6mr_cache_free_rcu(struct rcu_head *head)
{ {
struct mfc6_cache *c = container_of(head, struct mfc6_cache, rcu); struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
kmem_cache_free(mrt_cachep, c); kmem_cache_free(mrt_cachep, (struct mfc6_cache *)c);
} }
static inline void ip6mr_cache_free(struct mfc6_cache *c) static inline void ip6mr_cache_free(struct mfc6_cache *c)
{ {
call_rcu(&c->rcu, ip6mr_cache_free_rcu); call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu);
} }
/* Destroy an unresolved cache entry, killing queued skbs /* Destroy an unresolved cache entry, killing queued skbs
...@@ -821,7 +824,7 @@ static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c) ...@@ -821,7 +824,7 @@ static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
atomic_dec(&mrt->cache_resolve_queue_len); atomic_dec(&mrt->cache_resolve_queue_len);
while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) {
if (ipv6_hdr(skb)->version == 0) { if (ipv6_hdr(skb)->version == 0) {
struct nlmsghdr *nlh = skb_pull(skb, struct nlmsghdr *nlh = skb_pull(skb,
sizeof(struct ipv6hdr)); sizeof(struct ipv6hdr));
...@@ -844,7 +847,7 @@ static void ipmr_do_expire_process(struct mr_table *mrt) ...@@ -844,7 +847,7 @@ static void ipmr_do_expire_process(struct mr_table *mrt)
{ {
unsigned long now = jiffies; unsigned long now = jiffies;
unsigned long expires = 10 * HZ; unsigned long expires = 10 * HZ;
struct mfc6_cache *c, *next; struct mr_mfc *c, *next;
list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) { list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
if (time_after(c->mfc_un.unres.expires, now)) { if (time_after(c->mfc_un.unres.expires, now)) {
...@@ -856,8 +859,8 @@ static void ipmr_do_expire_process(struct mr_table *mrt) ...@@ -856,8 +859,8 @@ static void ipmr_do_expire_process(struct mr_table *mrt)
} }
list_del(&c->list); list_del(&c->list);
mr6_netlink_event(mrt, c, RTM_DELROUTE); mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
ip6mr_destroy_unres(mrt, c); ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
} }
if (!list_empty(&mrt->mfc_unres_queue)) if (!list_empty(&mrt->mfc_unres_queue))
...@@ -882,7 +885,7 @@ static void ipmr_expire_process(struct timer_list *t) ...@@ -882,7 +885,7 @@ static void ipmr_expire_process(struct timer_list *t)
/* Fill oifs list. It is called under write locked mrt_lock. */ /* Fill oifs list. It is called under write locked mrt_lock. */
static void ip6mr_update_thresholds(struct mr_table *mrt, static void ip6mr_update_thresholds(struct mr_table *mrt,
struct mfc6_cache *cache, struct mr_mfc *cache,
unsigned char *ttls) unsigned char *ttls)
{ {
int vifi; int vifi;
...@@ -986,11 +989,11 @@ static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt, ...@@ -986,11 +989,11 @@ static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
.mf6c_mcastgrp = *mcastgrp, .mf6c_mcastgrp = *mcastgrp,
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc6_cache *c; struct mr_mfc *c;
list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) rhl_for_each_entry_rcu(c, tmp, list, mnode)
return c; return (struct mfc6_cache *)c;
return NULL; return NULL;
} }
...@@ -1004,12 +1007,12 @@ static struct mfc6_cache *ip6mr_cache_find_any_parent(struct mr_table *mrt, ...@@ -1004,12 +1007,12 @@ static struct mfc6_cache *ip6mr_cache_find_any_parent(struct mr_table *mrt,
.mf6c_mcastgrp = in6addr_any, .mf6c_mcastgrp = in6addr_any,
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc6_cache *c; struct mr_mfc *c;
list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) rhl_for_each_entry_rcu(c, tmp, list, mnode)
if (c->mfc_un.res.ttls[mifi] < 255) if (c->mfc_un.res.ttls[mifi] < 255)
return c; return (struct mfc6_cache *)c;
return NULL; return NULL;
} }
...@@ -1024,7 +1027,8 @@ static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt, ...@@ -1024,7 +1027,8 @@ static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
.mf6c_mcastgrp = *mcastgrp, .mf6c_mcastgrp = *mcastgrp,
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc6_cache *c, *proxy; struct mr_mfc *c;
struct mfc6_cache *proxy;
if (ipv6_addr_any(mcastgrp)) if (ipv6_addr_any(mcastgrp))
goto skip; goto skip;
...@@ -1032,12 +1036,12 @@ static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt, ...@@ -1032,12 +1036,12 @@ static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) { rhl_for_each_entry_rcu(c, tmp, list, mnode) {
if (c->mfc_un.res.ttls[mifi] < 255) if (c->mfc_un.res.ttls[mifi] < 255)
return c; return (struct mfc6_cache *)c;
/* It's ok if the mifi is part of the static tree */ /* It's ok if the mifi is part of the static tree */
proxy = ip6mr_cache_find_any_parent(mrt, c->mf6c_parent); proxy = ip6mr_cache_find_any_parent(mrt, c->mfc_parent);
if (proxy && proxy->mfc_un.res.ttls[mifi] < 255) if (proxy && proxy->_c.mfc_un.res.ttls[mifi] < 255)
return c; return (struct mfc6_cache *)c;
} }
skip: skip:
...@@ -1056,12 +1060,12 @@ ip6mr_cache_find_parent(struct mr_table *mrt, ...@@ -1056,12 +1060,12 @@ ip6mr_cache_find_parent(struct mr_table *mrt,
.mf6c_mcastgrp = *mcastgrp, .mf6c_mcastgrp = *mcastgrp,
}; };
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct mfc6_cache *c; struct mr_mfc *c;
list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params); list = rhltable_lookup(&mrt->mfc_hash, &arg, ip6mr_rht_params);
rhl_for_each_entry_rcu(c, tmp, list, mnode) rhl_for_each_entry_rcu(c, tmp, list, mnode)
if (parent == -1 || parent == c->mf6c_parent) if (parent == -1 || parent == c->mfc_parent)
return c; return (struct mfc6_cache *)c;
return NULL; return NULL;
} }
...@@ -1074,8 +1078,8 @@ static struct mfc6_cache *ip6mr_cache_alloc(void) ...@@ -1074,8 +1078,8 @@ static struct mfc6_cache *ip6mr_cache_alloc(void)
struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
if (!c) if (!c)
return NULL; return NULL;
c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
c->mfc_un.res.minvif = MAXMIFS; c->_c.mfc_un.res.minvif = MAXMIFS;
return c; return c;
} }
...@@ -1084,8 +1088,8 @@ static struct mfc6_cache *ip6mr_cache_alloc_unres(void) ...@@ -1084,8 +1088,8 @@ static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
if (!c) if (!c)
return NULL; return NULL;
skb_queue_head_init(&c->mfc_un.unres.unresolved); skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
c->mfc_un.unres.expires = jiffies + 10 * HZ; c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
return c; return c;
} }
...@@ -1102,7 +1106,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt, ...@@ -1102,7 +1106,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
* Play the pending entries through our router * Play the pending entries through our router
*/ */
while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
if (ipv6_hdr(skb)->version == 0) { if (ipv6_hdr(skb)->version == 0) {
struct nlmsghdr *nlh = skb_pull(skb, struct nlmsghdr *nlh = skb_pull(skb,
sizeof(struct ipv6hdr)); sizeof(struct ipv6hdr));
...@@ -1221,19 +1225,16 @@ static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, ...@@ -1221,19 +1225,16 @@ static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
return ret; return ret;
} }
/* /* Queue a packet for resolution. It gets locked cache entry! */
* Queue a packet for resolution. It gets locked cache entry! static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
*/ struct sk_buff *skb)
static int
ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, struct sk_buff *skb)
{ {
struct mfc6_cache *c;
bool found = false; bool found = false;
int err; int err;
struct mfc6_cache *c;
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
list_for_each_entry(c, &mrt->mfc_unres_queue, list) { list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) && if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) { ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
found = true; found = true;
...@@ -1254,10 +1255,8 @@ ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, struct sk_buff *skb) ...@@ -1254,10 +1255,8 @@ ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, struct sk_buff *skb)
return -ENOBUFS; return -ENOBUFS;
} }
/* /* Fill in the new cache entry */
* Fill in the new cache entry c->_c.mfc_parent = -1;
*/
c->mf6c_parent = -1;
c->mf6c_origin = ipv6_hdr(skb)->saddr; c->mf6c_origin = ipv6_hdr(skb)->saddr;
c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr; c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
...@@ -1277,20 +1276,18 @@ ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, struct sk_buff *skb) ...@@ -1277,20 +1276,18 @@ ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, struct sk_buff *skb)
} }
atomic_inc(&mrt->cache_resolve_queue_len); atomic_inc(&mrt->cache_resolve_queue_len);
list_add(&c->list, &mrt->mfc_unres_queue); list_add(&c->_c.list, &mrt->mfc_unres_queue);
mr6_netlink_event(mrt, c, RTM_NEWROUTE); mr6_netlink_event(mrt, c, RTM_NEWROUTE);
ipmr_do_expire_process(mrt); ipmr_do_expire_process(mrt);
} }
/* /* See if we can append the packet */
* See if we can append the packet if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
*/
if (c->mfc_un.unres.unresolved.qlen > 3) {
kfree_skb(skb); kfree_skb(skb);
err = -ENOBUFS; err = -ENOBUFS;
} else { } else {
skb_queue_tail(&c->mfc_un.unres.unresolved, skb); skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
err = 0; err = 0;
} }
...@@ -1314,8 +1311,8 @@ static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc, ...@@ -1314,8 +1311,8 @@ static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
rcu_read_unlock(); rcu_read_unlock();
if (!c) if (!c)
return -ENOENT; return -ENOENT;
rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params); rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
list_del_rcu(&c->list); list_del_rcu(&c->_c.list);
mr6_netlink_event(mrt, c, RTM_DELROUTE); mr6_netlink_event(mrt, c, RTM_DELROUTE);
ip6mr_cache_free(c); ip6mr_cache_free(c);
...@@ -1454,6 +1451,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1454,6 +1451,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
{ {
unsigned char ttls[MAXMIFS]; unsigned char ttls[MAXMIFS];
struct mfc6_cache *uc, *c; struct mfc6_cache *uc, *c;
struct mr_mfc *_uc;
bool found; bool found;
int i, err; int i, err;
...@@ -1473,10 +1471,10 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1473,10 +1471,10 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
rcu_read_unlock(); rcu_read_unlock();
if (c) { if (c) {
write_lock_bh(&mrt_lock); write_lock_bh(&mrt_lock);
c->mf6c_parent = mfc->mf6cc_parent; c->_c.mfc_parent = mfc->mf6cc_parent;
ip6mr_update_thresholds(mrt, c, ttls); ip6mr_update_thresholds(mrt, &c->_c, ttls);
if (!mrtsock) if (!mrtsock)
c->mfc_flags |= MFC_STATIC; c->_c.mfc_flags |= MFC_STATIC;
write_unlock_bh(&mrt_lock); write_unlock_bh(&mrt_lock);
mr6_netlink_event(mrt, c, RTM_NEWROUTE); mr6_netlink_event(mrt, c, RTM_NEWROUTE);
return 0; return 0;
...@@ -1492,29 +1490,30 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1492,29 +1490,30 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
c->mf6c_parent = mfc->mf6cc_parent; c->_c.mfc_parent = mfc->mf6cc_parent;
ip6mr_update_thresholds(mrt, c, ttls); ip6mr_update_thresholds(mrt, &c->_c, ttls);
if (!mrtsock) if (!mrtsock)
c->mfc_flags |= MFC_STATIC; c->_c.mfc_flags |= MFC_STATIC;
err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->mnode, err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
ip6mr_rht_params); ip6mr_rht_params);
if (err) { if (err) {
pr_err("ip6mr: rhtable insert error %d\n", err); pr_err("ip6mr: rhtable insert error %d\n", err);
ip6mr_cache_free(c); ip6mr_cache_free(c);
return err; return err;
} }
list_add_tail_rcu(&c->list, &mrt->mfc_cache_list); list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
/* Check to see if we resolved a queued list. If so we /* Check to see if we resolved a queued list. If so we
* need to send on the frames and tidy up. * need to send on the frames and tidy up.
*/ */
found = false; found = false;
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
list_for_each_entry(uc, &mrt->mfc_unres_queue, list) { list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
uc = (struct mfc6_cache *)_uc;
if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) && if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) { ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
list_del(&uc->list); list_del(&_uc->list);
atomic_dec(&mrt->cache_resolve_queue_len); atomic_dec(&mrt->cache_resolve_queue_len);
found = true; found = true;
break; break;
...@@ -1538,7 +1537,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt, ...@@ -1538,7 +1537,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
static void mroute_clean_tables(struct mr_table *mrt, bool all) static void mroute_clean_tables(struct mr_table *mrt, bool all)
{ {
struct mfc6_cache *c, *tmp; struct mr_mfc *c, *tmp;
LIST_HEAD(list); LIST_HEAD(list);
int i; int i;
...@@ -1556,16 +1555,17 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all) ...@@ -1556,16 +1555,17 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
continue; continue;
rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params); rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
list_del_rcu(&c->list); list_del_rcu(&c->list);
mr6_netlink_event(mrt, c, RTM_DELROUTE); mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
ip6mr_cache_free(c); ip6mr_cache_free((struct mfc6_cache *)c);
} }
if (atomic_read(&mrt->cache_resolve_queue_len) != 0) { if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) { list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
list_del(&c->list); list_del(&c->list);
mr6_netlink_event(mrt, c, RTM_DELROUTE); mr6_netlink_event(mrt, (struct mfc6_cache *)c,
ip6mr_destroy_unres(mrt, c); RTM_DELROUTE);
ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
} }
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
} }
...@@ -1899,9 +1899,9 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) ...@@ -1899,9 +1899,9 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
rcu_read_lock(); rcu_read_lock();
c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
if (c) { if (c) {
sr.pktcnt = c->mfc_un.res.pkt; sr.pktcnt = c->_c.mfc_un.res.pkt;
sr.bytecnt = c->mfc_un.res.bytes; sr.bytecnt = c->_c.mfc_un.res.bytes;
sr.wrong_if = c->mfc_un.res.wrong_if; sr.wrong_if = c->_c.mfc_un.res.wrong_if;
rcu_read_unlock(); rcu_read_unlock();
if (copy_to_user(arg, &sr, sizeof(sr))) if (copy_to_user(arg, &sr, sizeof(sr)))
...@@ -1973,9 +1973,9 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) ...@@ -1973,9 +1973,9 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
rcu_read_lock(); rcu_read_lock();
c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
if (c) { if (c) {
sr.pktcnt = c->mfc_un.res.pkt; sr.pktcnt = c->_c.mfc_un.res.pkt;
sr.bytecnt = c->mfc_un.res.bytes; sr.bytecnt = c->_c.mfc_un.res.bytes;
sr.wrong_if = c->mfc_un.res.wrong_if; sr.wrong_if = c->_c.mfc_un.res.wrong_if;
rcu_read_unlock(); rcu_read_unlock();
if (copy_to_user(arg, &sr, sizeof(sr))) if (copy_to_user(arg, &sr, sizeof(sr)))
...@@ -2089,18 +2089,18 @@ static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev) ...@@ -2089,18 +2089,18 @@ static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
} }
static void ip6_mr_forward(struct net *net, struct mr_table *mrt, static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
struct sk_buff *skb, struct mfc6_cache *cache) struct sk_buff *skb, struct mfc6_cache *c)
{ {
int psend = -1; int psend = -1;
int vif, ct; int vif, ct;
int true_vifi = ip6mr_find_vif(mrt, skb->dev); int true_vifi = ip6mr_find_vif(mrt, skb->dev);
vif = cache->mf6c_parent; vif = c->_c.mfc_parent;
cache->mfc_un.res.pkt++; c->_c.mfc_un.res.pkt++;
cache->mfc_un.res.bytes += skb->len; c->_c.mfc_un.res.bytes += skb->len;
cache->mfc_un.res.lastuse = jiffies; c->_c.mfc_un.res.lastuse = jiffies;
if (ipv6_addr_any(&cache->mf6c_origin) && true_vifi >= 0) { if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
struct mfc6_cache *cache_proxy; struct mfc6_cache *cache_proxy;
/* For an (*,G) entry, we only check that the incoming /* For an (*,G) entry, we only check that the incoming
...@@ -2109,7 +2109,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2109,7 +2109,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
rcu_read_lock(); rcu_read_lock();
cache_proxy = ip6mr_cache_find_any_parent(mrt, vif); cache_proxy = ip6mr_cache_find_any_parent(mrt, vif);
if (cache_proxy && if (cache_proxy &&
cache_proxy->mfc_un.res.ttls[true_vifi] < 255) { cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
rcu_read_unlock(); rcu_read_unlock();
goto forward; goto forward;
} }
...@@ -2120,7 +2120,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2120,7 +2120,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
* Wrong interface: drop packet and (maybe) send PIM assert. * Wrong interface: drop packet and (maybe) send PIM assert.
*/ */
if (mrt->vif_table[vif].dev != skb->dev) { if (mrt->vif_table[vif].dev != skb->dev) {
cache->mfc_un.res.wrong_if++; c->_c.mfc_un.res.wrong_if++;
if (true_vifi >= 0 && mrt->mroute_do_assert && if (true_vifi >= 0 && mrt->mroute_do_assert &&
/* pimsm uses asserts, when switching from RPT to SPT, /* pimsm uses asserts, when switching from RPT to SPT,
...@@ -2129,10 +2129,11 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2129,10 +2129,11 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
large chunk of pimd to kernel. Ough... --ANK large chunk of pimd to kernel. Ough... --ANK
*/ */
(mrt->mroute_do_pim || (mrt->mroute_do_pim ||
cache->mfc_un.res.ttls[true_vifi] < 255) && c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
time_after(jiffies, time_after(jiffies,
cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { c->_c.mfc_un.res.last_assert +
cache->mfc_un.res.last_assert = jiffies; MFC_ASSERT_THRESH)) {
c->_c.mfc_un.res.last_assert = jiffies;
ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF); ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
} }
goto dont_forward; goto dont_forward;
...@@ -2145,36 +2146,38 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2145,36 +2146,38 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
/* /*
* Forward the frame * Forward the frame
*/ */
if (ipv6_addr_any(&cache->mf6c_origin) && if (ipv6_addr_any(&c->mf6c_origin) &&
ipv6_addr_any(&cache->mf6c_mcastgrp)) { ipv6_addr_any(&c->mf6c_mcastgrp)) {
if (true_vifi >= 0 && if (true_vifi >= 0 &&
true_vifi != cache->mf6c_parent && true_vifi != c->_c.mfc_parent &&
ipv6_hdr(skb)->hop_limit > ipv6_hdr(skb)->hop_limit >
cache->mfc_un.res.ttls[cache->mf6c_parent]) { c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
/* It's an (*,*) entry and the packet is not coming from /* It's an (*,*) entry and the packet is not coming from
* the upstream: forward the packet to the upstream * the upstream: forward the packet to the upstream
* only. * only.
*/ */
psend = cache->mf6c_parent; psend = c->_c.mfc_parent;
goto last_forward; goto last_forward;
} }
goto dont_forward; goto dont_forward;
} }
for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) { for (ct = c->_c.mfc_un.res.maxvif - 1;
ct >= c->_c.mfc_un.res.minvif; ct--) {
/* For (*,G) entry, don't forward to the incoming interface */ /* For (*,G) entry, don't forward to the incoming interface */
if ((!ipv6_addr_any(&cache->mf6c_origin) || ct != true_vifi) && if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) { ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
if (psend != -1) { if (psend != -1) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2) if (skb2)
ip6mr_forward2(net, mrt, skb2, cache, psend); ip6mr_forward2(net, mrt, skb2,
c, psend);
} }
psend = ct; psend = ct;
} }
} }
last_forward: last_forward:
if (psend != -1) { if (psend != -1) {
ip6mr_forward2(net, mrt, skb, cache, psend); ip6mr_forward2(net, mrt, skb, c, psend);
return; return;
} }
...@@ -2252,21 +2255,22 @@ static int __ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, ...@@ -2252,21 +2255,22 @@ static int __ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
int ct; int ct;
/* If cache is unresolved, don't try to parse IIF and OIF */ /* If cache is unresolved, don't try to parse IIF and OIF */
if (c->mf6c_parent >= MAXMIFS) { if (c->_c.mfc_parent >= MAXMIFS) {
rtm->rtm_flags |= RTNH_F_UNRESOLVED; rtm->rtm_flags |= RTNH_F_UNRESOLVED;
return -ENOENT; return -ENOENT;
} }
if (VIF_EXISTS(mrt, c->mf6c_parent) && if (VIF_EXISTS(mrt, c->_c.mfc_parent) &&
nla_put_u32(skb, RTA_IIF, nla_put_u32(skb, RTA_IIF,
mrt->vif_table[c->mf6c_parent].dev->ifindex) < 0) mrt->vif_table[c->_c.mfc_parent].dev->ifindex) < 0)
return -EMSGSIZE; return -EMSGSIZE;
mp_attr = nla_nest_start(skb, RTA_MULTIPATH); mp_attr = nla_nest_start(skb, RTA_MULTIPATH);
if (!mp_attr) if (!mp_attr)
return -EMSGSIZE; return -EMSGSIZE;
for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { for (ct = c->_c.mfc_un.res.minvif;
if (VIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) { ct < c->_c.mfc_un.res.maxvif; ct++) {
if (VIF_EXISTS(mrt, ct) && c->_c.mfc_un.res.ttls[ct] < 255) {
nhp = nla_reserve_nohdr(skb, sizeof(*nhp)); nhp = nla_reserve_nohdr(skb, sizeof(*nhp));
if (!nhp) { if (!nhp) {
nla_nest_cancel(skb, mp_attr); nla_nest_cancel(skb, mp_attr);
...@@ -2274,7 +2278,7 @@ static int __ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, ...@@ -2274,7 +2278,7 @@ static int __ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
} }
nhp->rtnh_flags = 0; nhp->rtnh_flags = 0;
nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; nhp->rtnh_hops = c->_c.mfc_un.res.ttls[ct];
nhp->rtnh_ifindex = mrt->vif_table[ct].dev->ifindex; nhp->rtnh_ifindex = mrt->vif_table[ct].dev->ifindex;
nhp->rtnh_len = sizeof(*nhp); nhp->rtnh_len = sizeof(*nhp);
} }
...@@ -2282,12 +2286,12 @@ static int __ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, ...@@ -2282,12 +2286,12 @@ static int __ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
nla_nest_end(skb, mp_attr); nla_nest_end(skb, mp_attr);
lastuse = READ_ONCE(c->mfc_un.res.lastuse); lastuse = READ_ONCE(c->_c.mfc_un.res.lastuse);
lastuse = time_after_eq(jiffies, lastuse) ? jiffies - lastuse : 0; lastuse = time_after_eq(jiffies, lastuse) ? jiffies - lastuse : 0;
mfcs.mfcs_packets = c->mfc_un.res.pkt; mfcs.mfcs_packets = c->_c.mfc_un.res.pkt;
mfcs.mfcs_bytes = c->mfc_un.res.bytes; mfcs.mfcs_bytes = c->_c.mfc_un.res.bytes;
mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if; mfcs.mfcs_wrong_if = c->_c.mfc_un.res.wrong_if;
if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) || if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) ||
nla_put_u64_64bit(skb, RTA_EXPIRES, jiffies_to_clock_t(lastuse), nla_put_u64_64bit(skb, RTA_EXPIRES, jiffies_to_clock_t(lastuse),
RTA_PAD)) RTA_PAD))
...@@ -2363,7 +2367,7 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, ...@@ -2363,7 +2367,7 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
} }
if (rtm->rtm_flags & RTM_F_NOTIFY) if (rtm->rtm_flags & RTM_F_NOTIFY)
cache->mfc_flags |= MFC_NOTIFY; cache->_c.mfc_flags |= MFC_NOTIFY;
err = __ip6mr_fill_mroute(mrt, skb, cache, rtm); err = __ip6mr_fill_mroute(mrt, skb, cache, rtm);
read_unlock(&mrt_lock); read_unlock(&mrt_lock);
...@@ -2392,7 +2396,7 @@ static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, ...@@ -2392,7 +2396,7 @@ static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
goto nla_put_failure; goto nla_put_failure;
rtm->rtm_type = RTN_MULTICAST; rtm->rtm_type = RTN_MULTICAST;
rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_scope = RT_SCOPE_UNIVERSE;
if (c->mfc_flags & MFC_STATIC) if (c->_c.mfc_flags & MFC_STATIC)
rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_protocol = RTPROT_STATIC;
else else
rtm->rtm_protocol = RTPROT_MROUTED; rtm->rtm_protocol = RTPROT_MROUTED;
...@@ -2442,7 +2446,7 @@ static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc, ...@@ -2442,7 +2446,7 @@ static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
struct sk_buff *skb; struct sk_buff *skb;
int err = -ENOBUFS; int err = -ENOBUFS;
skb = nlmsg_new(mr6_msgsize(mfc->mf6c_parent >= MAXMIFS, mrt->maxvif), skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
GFP_ATOMIC); GFP_ATOMIC);
if (!skb) if (!skb)
goto errout; goto errout;
...@@ -2528,10 +2532,10 @@ static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt) ...@@ -2528,10 +2532,10 @@ static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct mr_table *mrt;
struct mfc6_cache *mfc;
unsigned int t = 0, s_t; unsigned int t = 0, s_t;
unsigned int e = 0, s_e; unsigned int e = 0, s_e;
struct mr_table *mrt;
struct mr_mfc *mfc;
s_t = cb->args[0]; s_t = cb->args[0];
s_e = cb->args[1]; s_e = cb->args[1];
...@@ -2546,8 +2550,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2546,8 +2550,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
if (ip6mr_fill_mroute(mrt, skb, if (ip6mr_fill_mroute(mrt, skb,
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
mfc, RTM_NEWROUTE, (struct mfc6_cache *)mfc,
NLM_F_MULTI) < 0) RTM_NEWROUTE, NLM_F_MULTI) < 0)
goto done; goto done;
next_entry: next_entry:
e++; e++;
...@@ -2562,8 +2566,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2562,8 +2566,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
if (ip6mr_fill_mroute(mrt, skb, if (ip6mr_fill_mroute(mrt, skb,
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
mfc, RTM_NEWROUTE, (struct mfc6_cache *)mfc,
NLM_F_MULTI) < 0) { RTM_NEWROUTE, NLM_F_MULTI) < 0) {
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
goto done; goto done;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment