diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-09-12 17:27:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-09-12 17:27:37 -0400 |
commit | e21ce8c7c013fb223a002c70bb0a547de6c26c12 (patch) | |
tree | 767b9aae7bdd50cdf867f3cdc1a3e214692146e1 | |
parent | d2ce4bc340946d5b78484d638ac10df958c4c3bf (diff) |
[NETROM]: Implement G8PZT Circuit reset for NET/ROM
NET/ROM is lacking a connection reset like TCP's RST flag which at times
may result in a connecting having to slowly timing out instead of just being
reset. An earlier attempt to reset the connection by sending a
NR_CONNACK | NR_CHOKE_FLAG transport was inacceptable as it did result in
crashes of BPQ systems. An alternative approach of introducing a new
transport type 7 (NR_RESET) has be implemented several years ago in
Paula Jayne Dowie G8PZT's Xrouter.
Implement NR_RESET for Linux's NET/ROM but like any messing with the state
engine consider this experimental for now and thus control it by a sysctl
(net.netrom.reset) which for the time being defaults to off.
Signed-off-by: Ralf Baechle DL5RB <ralf@linux-mips.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/sysctl.h | 3 | ||||
-rw-r--r-- | include/net/netrom.h | 27 | ||||
-rw-r--r-- | net/netrom/af_netrom.c | 21 | ||||
-rw-r--r-- | net/netrom/nr_in.c | 15 | ||||
-rw-r--r-- | net/netrom/nr_subr.c | 7 | ||||
-rw-r--r-- | net/netrom/sysctl_net_netrom.c | 12 |
6 files changed, 69 insertions, 16 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 532a6c5c24e9..3a29a9f9b451 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
@@ -544,7 +544,8 @@ enum { | |||
544 | NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8, | 544 | NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8, |
545 | NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9, | 545 | NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9, |
546 | NET_NETROM_ROUTING_CONTROL=10, | 546 | NET_NETROM_ROUTING_CONTROL=10, |
547 | NET_NETROM_LINK_FAILS_COUNT=11 | 547 | NET_NETROM_LINK_FAILS_COUNT=11, |
548 | NET_NETROM_RESET=12 | ||
548 | }; | 549 | }; |
549 | 550 | ||
550 | /* /proc/sys/net/ax25 */ | 551 | /* /proc/sys/net/ax25 */ |
diff --git a/include/net/netrom.h b/include/net/netrom.h index 45f2c7616d8b..ad05d7a3c55d 100644 --- a/include/net/netrom.h +++ b/include/net/netrom.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define NR_DISCACK 0x04 | 22 | #define NR_DISCACK 0x04 |
23 | #define NR_INFO 0x05 | 23 | #define NR_INFO 0x05 |
24 | #define NR_INFOACK 0x06 | 24 | #define NR_INFOACK 0x06 |
25 | #define NR_RESET 0x07 | ||
25 | 26 | ||
26 | #define NR_CHOKE_FLAG 0x80 | 27 | #define NR_CHOKE_FLAG 0x80 |
27 | #define NR_NAK_FLAG 0x40 | 28 | #define NR_NAK_FLAG 0x40 |
@@ -51,6 +52,7 @@ enum { | |||
51 | #define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */ | 52 | #define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */ |
52 | #define NR_DEFAULT_ROUTING 1 /* Is routing enabled ? */ | 53 | #define NR_DEFAULT_ROUTING 1 /* Is routing enabled ? */ |
53 | #define NR_DEFAULT_FAILS 2 /* Link fails until route fails */ | 54 | #define NR_DEFAULT_FAILS 2 /* Link fails until route fails */ |
55 | #define NR_DEFAULT_RESET 0 /* Sent / accept reset cmds? */ | ||
54 | 56 | ||
55 | #define NR_MODULUS 256 | 57 | #define NR_MODULUS 256 |
56 | #define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */ | 58 | #define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */ |
@@ -176,6 +178,8 @@ extern int sysctl_netrom_transport_requested_window_size; | |||
176 | extern int sysctl_netrom_transport_no_activity_timeout; | 178 | extern int sysctl_netrom_transport_no_activity_timeout; |
177 | extern int sysctl_netrom_routing_control; | 179 | extern int sysctl_netrom_routing_control; |
178 | extern int sysctl_netrom_link_fails_count; | 180 | extern int sysctl_netrom_link_fails_count; |
181 | extern int sysctl_netrom_reset_circuit; | ||
182 | |||
179 | extern int nr_rx_frame(struct sk_buff *, struct net_device *); | 183 | extern int nr_rx_frame(struct sk_buff *, struct net_device *); |
180 | extern void nr_destroy_socket(struct sock *); | 184 | extern void nr_destroy_socket(struct sock *); |
181 | 185 | ||
@@ -218,7 +222,28 @@ extern void nr_requeue_frames(struct sock *); | |||
218 | extern int nr_validate_nr(struct sock *, unsigned short); | 222 | extern int nr_validate_nr(struct sock *, unsigned short); |
219 | extern int nr_in_rx_window(struct sock *, unsigned short); | 223 | extern int nr_in_rx_window(struct sock *, unsigned short); |
220 | extern void nr_write_internal(struct sock *, int); | 224 | extern void nr_write_internal(struct sock *, int); |
221 | extern void nr_transmit_refusal(struct sk_buff *, int); | 225 | |
226 | extern void __nr_transmit_reply(struct sk_buff *skb, int mine, | ||
227 | unsigned char cmdflags); | ||
228 | |||
229 | /* | ||
230 | * This routine is called when a Connect Acknowledge with the Choke Flag | ||
231 | * set is needed to refuse a connection. | ||
232 | */ | ||
233 | #define nr_transmit_refusal(skb, mine) \ | ||
234 | do { \ | ||
235 | __nr_transmit_reply((skb), (mine), NR_CONNACK | NR_CHOKE_FLAG); \ | ||
236 | } while (0) | ||
237 | |||
238 | /* | ||
239 | * This routine is called when we don't have a circuit matching an incoming | ||
240 | * NET/ROM packet. This is an G8PZT Xrouter extension. | ||
241 | */ | ||
242 | #define nr_transmit_reset(skb, mine) \ | ||
243 | do { \ | ||
244 | __nr_transmit_reply((skb), (mine), NR_RESET); \ | ||
245 | } while (0) | ||
246 | |||
222 | extern void nr_disconnect(struct sock *, int); | 247 | extern void nr_disconnect(struct sock *, int); |
223 | 248 | ||
224 | /* nr_timer.c */ | 249 | /* nr_timer.c */ |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 02b1ab52dbbf..8c3d3a78481e 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -56,6 +56,7 @@ int sysctl_netrom_transport_requested_window_size = NR_DEFAULT_WINDOW; | |||
56 | int sysctl_netrom_transport_no_activity_timeout = NR_DEFAULT_IDLE; | 56 | int sysctl_netrom_transport_no_activity_timeout = NR_DEFAULT_IDLE; |
57 | int sysctl_netrom_routing_control = NR_DEFAULT_ROUTING; | 57 | int sysctl_netrom_routing_control = NR_DEFAULT_ROUTING; |
58 | int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS; | 58 | int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS; |
59 | int sysctl_netrom_reset_circuit = NR_DEFAULT_RESET; | ||
59 | 60 | ||
60 | static unsigned short circuit = 0x101; | 61 | static unsigned short circuit = 0x101; |
61 | 62 | ||
@@ -908,17 +909,17 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) | |||
908 | if (frametype != NR_CONNREQ) { | 909 | if (frametype != NR_CONNREQ) { |
909 | /* | 910 | /* |
910 | * Here it would be nice to be able to send a reset but | 911 | * Here it would be nice to be able to send a reset but |
911 | * NET/ROM doesn't have one. The following hack would | 912 | * NET/ROM doesn't have one. We've tried to extend the protocol |
912 | * have been a way to extend the protocol but apparently | 913 | * by sending NR_CONNACK | NR_CHOKE_FLAGS replies but that |
913 | * it kills BPQ boxes... :-( | 914 | * apparently kills BPQ boxes... :-( |
915 | * So now we try to follow the established behaviour of | ||
916 | * G8PZT's Xrouter which is sending packets with command type 7 | ||
917 | * as an extension of the protocol. | ||
914 | */ | 918 | */ |
915 | #if 0 | 919 | if (sysctl_netrom_reset_circuit && |
916 | /* | 920 | (frametype != NR_RESET || flags != 0)) |
917 | * Never reply to a CONNACK/CHOKE. | 921 | nr_transmit_reset(skb, 1); |
918 | */ | 922 | |
919 | if (frametype != NR_CONNACK || flags != NR_CHOKE_FLAG) | ||
920 | nr_transmit_refusal(skb, 1); | ||
921 | #endif | ||
922 | return 0; | 923 | return 0; |
923 | } | 924 | } |
924 | 925 | ||
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c index 64b81a796907..004e8599b8fe 100644 --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c | |||
@@ -98,6 +98,11 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, | |||
98 | nr_disconnect(sk, ECONNREFUSED); | 98 | nr_disconnect(sk, ECONNREFUSED); |
99 | break; | 99 | break; |
100 | 100 | ||
101 | case NR_RESET: | ||
102 | if (sysctl_netrom_reset_circuit); | ||
103 | nr_disconnect(sk, ECONNRESET); | ||
104 | break; | ||
105 | |||
101 | default: | 106 | default: |
102 | break; | 107 | break; |
103 | } | 108 | } |
@@ -124,6 +129,11 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, | |||
124 | nr_disconnect(sk, 0); | 129 | nr_disconnect(sk, 0); |
125 | break; | 130 | break; |
126 | 131 | ||
132 | case NR_RESET: | ||
133 | if (sysctl_netrom_reset_circuit); | ||
134 | nr_disconnect(sk, ECONNRESET); | ||
135 | break; | ||
136 | |||
127 | default: | 137 | default: |
128 | break; | 138 | break; |
129 | } | 139 | } |
@@ -254,6 +264,11 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype | |||
254 | } | 264 | } |
255 | break; | 265 | break; |
256 | 266 | ||
267 | case NR_RESET: | ||
268 | if (sysctl_netrom_reset_circuit); | ||
269 | nr_disconnect(sk, ECONNRESET); | ||
270 | break; | ||
271 | |||
257 | default: | 272 | default: |
258 | break; | 273 | break; |
259 | } | 274 | } |
diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c index 587bed2674bf..bcb9946b4f56 100644 --- a/net/netrom/nr_subr.c +++ b/net/netrom/nr_subr.c | |||
@@ -210,10 +210,9 @@ void nr_write_internal(struct sock *sk, int frametype) | |||
210 | } | 210 | } |
211 | 211 | ||
212 | /* | 212 | /* |
213 | * This routine is called when a Connect Acknowledge with the Choke Flag | 213 | * This routine is called to send an error reply. |
214 | * set is needed to refuse a connection. | ||
215 | */ | 214 | */ |
216 | void nr_transmit_refusal(struct sk_buff *skb, int mine) | 215 | void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags) |
217 | { | 216 | { |
218 | struct sk_buff *skbn; | 217 | struct sk_buff *skbn; |
219 | unsigned char *dptr; | 218 | unsigned char *dptr; |
@@ -254,7 +253,7 @@ void nr_transmit_refusal(struct sk_buff *skb, int mine) | |||
254 | *dptr++ = 0; | 253 | *dptr++ = 0; |
255 | } | 254 | } |
256 | 255 | ||
257 | *dptr++ = NR_CONNACK | NR_CHOKE_FLAG; | 256 | *dptr++ = cmdflags; |
258 | *dptr++ = 0; | 257 | *dptr++ = 0; |
259 | 258 | ||
260 | if (!nr_route_frame(skbn, NULL)) | 259 | if (!nr_route_frame(skbn, NULL)) |
diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c index c9ed50382ea7..6bb8dda849dc 100644 --- a/net/netrom/sysctl_net_netrom.c +++ b/net/netrom/sysctl_net_netrom.c | |||
@@ -30,6 +30,7 @@ static int min_idle[] = {0 * HZ}; | |||
30 | static int max_idle[] = {65535 * HZ}; | 30 | static int max_idle[] = {65535 * HZ}; |
31 | static int min_route[] = {0}, max_route[] = {1}; | 31 | static int min_route[] = {0}, max_route[] = {1}; |
32 | static int min_fails[] = {1}, max_fails[] = {10}; | 32 | static int min_fails[] = {1}, max_fails[] = {10}; |
33 | static int min_reset[] = {0}, max_reset[] = {1}; | ||
33 | 34 | ||
34 | static struct ctl_table_header *nr_table_header; | 35 | static struct ctl_table_header *nr_table_header; |
35 | 36 | ||
@@ -155,6 +156,17 @@ static ctl_table nr_table[] = { | |||
155 | .extra1 = &min_fails, | 156 | .extra1 = &min_fails, |
156 | .extra2 = &max_fails | 157 | .extra2 = &max_fails |
157 | }, | 158 | }, |
159 | { | ||
160 | .ctl_name = NET_NETROM_RESET, | ||
161 | .procname = "reset", | ||
162 | .data = &sysctl_netrom_reset_circuit, | ||
163 | .maxlen = sizeof(int), | ||
164 | .mode = 0644, | ||
165 | .proc_handler = &proc_dointvec_minmax, | ||
166 | .strategy = &sysctl_intvec, | ||
167 | .extra1 = &min_reset, | ||
168 | .extra2 = &max_reset | ||
169 | }, | ||
158 | { .ctl_name = 0 } | 170 | { .ctl_name = 0 } |
159 | }; | 171 | }; |
160 | 172 | ||