Proper reference counting for AX.25 routes.
PATCH 1/1 Proper reference counting for AX.25 routes.
Below patch fixes the reference counting for AX.25 routes. It also gets rid of the timer madness which currently is being used for routing table entries that are still busy at the time of their removal from the routing table.
Please test this,
73 de DL5RB op Ralf
--
Loc. JN47BS / CQ 14 / ITU 28 / DOK A21
Signed-off-by Ralf Baechle DL5RB <[email protected]>
include/net/ax25.h | 24 +++++++++++++++--------- net/ax25/ax25_ip.c | 23 +++++++++++++++-------- net/ax25/ax25_route.c | 49 ++++++++----------------------------------------- 3 files changed, 38 insertions(+), 58 deletions(-)
include/net/ax25.h +15 -9
@@ -183,14 +183,26 @@ typedef struct {typedef struct ax25_route {struct ax25_route *next; -atomic_t ref; +atomic_t refcount;ax25_address callsign;struct net_device *dev;ax25_digi *digipeat;char ip_mode; -struct timer_list timer; }ax25_route ; +static inline void ax25_hold_route (ax25_route *ax25_rt) +{ +atomic_inc (&ax25_rt->refcount); +} + +extern void __ax25_put_route (ax25_route *ax25_rt); + +static inline void ax25_put_route (ax25_route *ax25_rt) +{ +if (atomic_dec_and_test (&ax25_rt->refcount)) +__ax25_put_route (ax25_rt); +} + typedef struct { char slave; /* slave_mode? */ struct timer_list slave_timer; /* timeout timer */
@@ -349,17 +361,11 @@ extern int ax25_check_iframes_acked(ax2extern void ax25_rt_device_down (struct net_device *);extern int ax25_rt_ioctl (unsigned int ,void __user *);extern struct file_operations ax25_route_fops; +extern ax25_route *ax25_get_route (ax25_address *addr,struct net_device *dev);extern int ax25_rt_autobind (ax25_cb *,ax25_address *); -extern ax25_route *ax25_rt_find_route (ax25_route *,ax25_address *, -struct net_device *);extern struct sk_buff *ax25_rt_build_path (struct sk_buff *,ax25_address *,ax25_address *,ax25_digi *);extern void ax25_rt_free (void ); -static inline void ax25_put_route (ax25_route *ax25_rt) -{ -atomic_dec (&ax25_rt->ref); -} -/* ax25_std_in.c */ extern int ax25_std_frame_in (ax25_cb *,struct sk_buff *,int );
net/ax25/ax25_ip.c +15 -8
@@ -104,11 +104,13 @@ int ax25_rebuild_header(struct sk_buff * {struct sk_buff *ourskb;unsigned char *bp = skb->data; -struct net_device *dev; +ax25_route *route; +struct net_device *dev =NULL ;ax25_address *src, *dst; +ax25_digi *digipeat =NULL ;ax25_dev *ax25_dev; -ax25_route _route, *route = &_route;ax25_cb *ax25; +char ip_mode =' ' ; dst = (ax25_address *)(bp +1 ); src = (ax25_address *)(bp +8 );
@@ -116,8 +118,12 @@ int ax25_rebuild_header(struct sk_buff *if (arp_find (bp +1 , skb))return 1 ; - route =ax25_rt_find_route (route, dst,NULL ); - dev = route->dev; + route =ax25_get_route (dst,NULL ); +if (route) { + digipeat = route->digipeat; + dev = route->dev; + ip_mode = route->ip_mode; + };if (dev ==NULL ) dev = skb->dev;
@@ -127,7 +133,7 @@ int ax25_rebuild_header(struct sk_buff * }if (bp[16 ] ==AX25_P_IP ) { -if (route->ip_mode =='V' || (route->ip_mode ==' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE ])) { +if (ip_mode =='V' || (ip_mode ==' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE ])) {/* * We copy the buffer and release the original thereby * keeping it straight
@@ -173,7 +179,7 @@ int ax25_rebuild_header(struct sk_buff * ourskb, ax25_dev->values[AX25_VALUES_PACLEN ], &src_c, - &dst_c, route->digipeat, dev); + &dst_c, digipeat, dev);if (ax25) {ax25_cb_put (ax25); }
@@ -191,7 +197,7 @@ int ax25_rebuild_header(struct sk_buff *skb_pull (skb,AX25_KISS_HEADER_LEN ); -if (route->digipeat !=NULL ) { +if (digipeat !=NULL ) {if ((ourskb =ax25_rt_build_path (skb, src, dst, route->digipeat)) ==NULL ) {kfree_skb (skb); goto put;
@@ -203,7 +209,8 @@ int ax25_rebuild_header(struct sk_buff *ax25_queue_xmit (skb, dev); put: -ax25_put_route (route); +if (route) +ax25_put_route (route);return 1 ; }
net/ax25/ax25_route.c +8 -41
96 lines not on this page · raw message