Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rose: improving AX25 routing frames via ROSE network

ROSE network is organized through nodes connected via hamradio or Internet.
AX25 packet radio frames sent to a remote ROSE address destination are routed
through these nodes.

Without the present patch, automatic routing mechanism did not work optimally
due to an improper parameter checking.

rose_get_neigh() function is called either by rose_connect() or by
rose_route_frame().

In the case of a call from rose_connect(), f0 timer is checked to find if a connection
is already pending. In that case it returns the address of the neighbour, or returns a NULL otherwise.

When called by rose_route_frame() the purpose was to route a packet AX25 frame
through an adjacent node given a destination rose address.
However, in that case, t0 timer checked does not indicate if the adjacent node
is actually connected even if the timer is not null. Thus, for each frame sent, the
function often tried to start a new connexion even if the adjacent node was already connected.

The patch adds a "new" parameter that is true when the function is called by
rose route_frame().
This instructs rose_get_neigh() to check node parameter "restarted".
If restarted is true it means that the route to the destination address is opened via a neighbour
node already connected.
If "restarted" is false the function returns a NULL.
In that case the calling function will initiate a new connection as before.

This results in a fast routing of frames, from nodes to nodes, until
destination is reached, as originaly specified by ROSE protocole.

Signed-off-by: Bernard Pidoux <f6bvp@amsat.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Bernard Pidoux and committed by
David S. Miller
fe2c802a e92481f9

+21 -14
+1 -1
include/net/rose.h
··· 201 201 extern struct net_device *rose_dev_first(void); 202 202 extern struct net_device *rose_dev_get(rose_address *); 203 203 extern struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *); 204 - extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *); 204 + extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *, int); 205 205 extern int rose_rt_ioctl(unsigned int, void __user *); 206 206 extern void rose_link_failed(ax25_cb *, int); 207 207 extern int rose_route_frame(struct sk_buff *, ax25_cb *);
+2 -2
net/rose/af_rose.c
··· 757 757 sock->state = SS_UNCONNECTED; 758 758 759 759 rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, 760 - &diagnostic); 760 + &diagnostic, 0); 761 761 if (!rose->neighbour) { 762 762 err = -ENETUNREACH; 763 763 goto out_release; ··· 853 853 854 854 if (sk->sk_state != TCP_ESTABLISHED) { 855 855 /* Try next neighbour */ 856 - rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic); 856 + rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic, 0); 857 857 if (rose->neighbour) 858 858 goto rose_try_next_neigh; 859 859
+18 -11
net/rose/rose_route.c
··· 662 662 } 663 663 664 664 /* 665 - * Find a neighbour given a ROSE address. 665 + * Find a neighbour or a route given a ROSE address. 666 666 */ 667 667 struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, 668 - unsigned char *diagnostic) 668 + unsigned char *diagnostic, int new) 669 669 { 670 670 struct rose_neigh *res = NULL; 671 671 struct rose_node *node; 672 672 int failed = 0; 673 673 int i; 674 674 675 - spin_lock_bh(&rose_node_list_lock); 675 + if (!new) spin_lock_bh(&rose_node_list_lock); 676 676 for (node = rose_node_list; node != NULL; node = node->next) { 677 677 if (rosecmpm(addr, &node->address, node->mask) == 0) { 678 678 for (i = 0; i < node->count; i++) { 679 - if (!rose_ftimer_running(node->neighbour[i])) { 680 - res = node->neighbour[i]; 681 - goto out; 682 - } else 683 - failed = 1; 679 + if (new) { 680 + if (node->neighbour[i]->restarted) { 681 + res = node->neighbour[i]; 682 + goto out; 683 + } 684 + } 685 + else { 686 + if (!rose_ftimer_running(node->neighbour[i])) { 687 + res = node->neighbour[i]; 688 + goto out; 689 + } else 690 + failed = 1; 691 + } 684 692 } 685 - break; 686 693 } 687 694 } 688 695 ··· 702 695 } 703 696 704 697 out: 705 - spin_unlock_bh(&rose_node_list_lock); 698 + if (!new) spin_unlock_bh(&rose_node_list_lock); 706 699 707 700 return res; 708 701 } ··· 1025 1018 rose_route = rose_route->next; 1026 1019 } 1027 1020 1028 - if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic)) == NULL) { 1021 + if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic, 1)) == NULL) { 1029 1022 rose_transmit_clear_request(rose_neigh, lci, cause, diagnostic); 1030 1023 goto out; 1031 1024 }