aboutsummaryrefslogtreecommitdiff
path: root/net/rose
diff options
context:
space:
mode:
authorBernard Pidoux <f6bvp@amsat.org>2008-06-17 17:08:32 -0700
committerDavid S. Miller <davem@davemloft.net>2008-06-17 17:08:32 -0700
commitfe2c802ab62aa63d276deafa905875f3455f2621 (patch)
treed1c18ba0e95e3ed522b216673e57ec795da99a41 /net/rose
parente92481f95375aa2702ea5018b0295792ae0fa9c1 (diff)
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>
Diffstat (limited to 'net/rose')
-rw-r--r--net/rose/af_rose.c4
-rw-r--r--net/rose/rose_route.c29
2 files changed, 20 insertions, 13 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index af86bcb604e..46461a69cd0 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -757,7 +757,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
sock->state = SS_UNCONNECTED;
rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,
- &diagnostic);
+ &diagnostic, 0);
if (!rose->neighbour) {
err = -ENETUNREACH;
goto out_release;
@@ -853,7 +853,7 @@ rose_try_next_neigh:
if (sk->sk_state != TCP_ESTABLISHED) {
/* Try next neighbour */
- rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic);
+ rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic, 0);
if (rose->neighbour)
goto rose_try_next_neigh;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index bd593871c81..a81066a1010 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -662,27 +662,34 @@ struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neig
}
/*
- * Find a neighbour given a ROSE address.
+ * Find a neighbour or a route given a ROSE address.
*/
struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
- unsigned char *diagnostic)
+ unsigned char *diagnostic, int new)
{
struct rose_neigh *res = NULL;
struct rose_node *node;
int failed = 0;
int i;
- spin_lock_bh(&rose_node_list_lock);
+ if (!new) spin_lock_bh(&rose_node_list_lock);
for (node = rose_node_list; node != NULL; node = node->next) {
if (rosecmpm(addr, &node->address, node->mask) == 0) {
for (i = 0; i < node->count; i++) {
- if (!rose_ftimer_running(node->neighbour[i])) {
- res = node->neighbour[i];
- goto out;
- } else
- failed = 1;
+ if (new) {
+ if (node->neighbour[i]->restarted) {
+ res = node->neighbour[i];
+ goto out;
+ }
+ }
+ else {
+ if (!rose_ftimer_running(node->neighbour[i])) {
+ res = node->neighbour[i];
+ goto out;
+ } else
+ failed = 1;
+ }
}
- break;
}
}
@@ -695,7 +702,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
}
out:
- spin_unlock_bh(&rose_node_list_lock);
+ if (!new) spin_unlock_bh(&rose_node_list_lock);
return res;
}
@@ -1018,7 +1025,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
rose_route = rose_route->next;
}
- if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic)) == NULL) {
+ if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic, 1)) == NULL) {
rose_transmit_clear_request(rose_neigh, lci, cause, diagnostic);
goto out;
}