Commit | Line | Data |
---|---|---|
af8c695d SL |
1 | |
2 | #include "../h/param.h" | |
3 | #include "../h/systm.h" | |
4 | #include "../h/mbuf.h" | |
5 | #include "../h/protosw.h" | |
6 | #include "../h/socket.h" | |
7 | #include "../h/socketvar.h" | |
8 | #include "../net/dn_systm.h" | |
9 | #include "../net/nsp.h" | |
10 | #include "../net/nsp_var.h" | |
11 | #include "../errno.h" | |
12 | ||
13 | int nspidebug = 1; | |
14 | #define printd if(nspidebug)printf | |
15 | /* | |
16 | * NSP input routine: decode incoming packet and dispatch | |
17 | * to appropriate socket. Called from the software interrupt | |
18 | * at splnet. | |
19 | * | |
20 | * TODO: | |
21 | * count occurances of various error conditions. | |
22 | */ | |
23 | ||
24 | nspintr() | |
25 | { | |
26 | struct mbuf *m; | |
27 | struct tprh *t; | |
28 | int s, bom, eom; | |
29 | u_short srcnode; | |
30 | char *p; | |
31 | struct nspcb *np; | |
32 | ||
33 | /* | |
34 | * Loop pulling packets off the interrupt queue. | |
35 | */ | |
36 | next: | |
37 | s = splimp(); | |
38 | IF_DEQUEUE(&nspintrq, m); | |
39 | splx(s); | |
40 | printd("nsp_input: m 0x%x", m); | |
41 | if (m == 0) | |
42 | return; | |
43 | t = mtod(m, struct tprh *); | |
44 | srcnode = t->tprh_srcnode; | |
45 | m->m_len -= sizeof (struct tprh); /* use m_adj??? */ | |
46 | m->m_off += sizeof (struct tprh); | |
47 | printd(", srcnode %d, len %d", srcnode, m->m_len); | |
48 | if (m->m_len <= 0) { | |
49 | m_freem(m); | |
50 | goto next; | |
51 | } | |
52 | ||
53 | /* | |
54 | * Switch on the type of the message. | |
55 | */ | |
56 | p = mtod(m, char *); | |
57 | switch (*p) { | |
58 | ||
59 | /* | |
60 | * Got a Data message, possibly with EOM and | |
61 | * BOM flags set. Call nsp_chkaddr to do ack | |
62 | * and flow controll processing, then pass the | |
63 | * data to the user. | |
64 | */ | |
65 | case NSP_DATA|NSP_EOM|NSP_BOM: | |
66 | eom = bom = 1; | |
67 | goto data; | |
68 | ||
69 | case NSP_DATA|NSP_EOM: | |
70 | eom = 1; | |
71 | goto data; | |
72 | ||
73 | case NSP_DATA|NSP_BOM: | |
74 | bom = 1; | |
75 | ||
76 | case NSP_DATA: | |
77 | data: | |
78 | printd(", DATA (%d,%d)", bom, eom); | |
79 | np = nsp_chkaddr(m, srcnode, NSP_DATA, &segnum); | |
80 | if (np == 0) { | |
81 | m_freem(m); | |
82 | goto next; | |
83 | } | |
84 | ||
85 | /* | |
86 | * Data messages only valid in Run state | |
87 | */ | |
88 | if (np->n_state != NS_RUN) { | |
89 | printf(", !RUN (%d)\n", np->n_state); | |
90 | m_freem(m); | |
91 | goto next; | |
92 | } | |
93 | if (SEQ_GTR(segnum, np->na_xmtdat)) { | |
94 | /* SHOULD DO SEGMENT RECONSTRUCTION HERE */ | |
95 | printd(", got data!"); | |
96 | sbpappend(m, &np->n_socket->sb_rcv); | |
97 | } else | |
98 | np->n_flags |= NF_DATACK; | |
99 | break; | |
100 | ||
101 | /* | |
102 | * Got an interrupt message. Call nsp_chkaddr | |
103 | * (as usual). Save the interrupt data for the | |
104 | * user. | |
105 | * GENERATE A SIGNAL OF SOME SORT??? | |
106 | */ | |
107 | case NSP_INTR: | |
108 | printd(", INTR"); | |
109 | np = nsp_chkaddr(m, srcnode, NSP_INTR, &segnum); | |
110 | if (np == 0) { | |
111 | m_freem(m); | |
112 | goto next; | |
113 | } | |
114 | ||
115 | /* | |
116 | * If we are in the Connect Confirm state then | |
117 | * this Interrupt packet causes the transition | |
118 | * to the Run state. Otherwise we better be in | |
119 | * the Run state already. | |
120 | */ | |
121 | if (np->n_state == NS_CC) | |
122 | np->n_state = NS_RUN; | |
123 | else if (np->n_state != NS_RUN) { | |
124 | printf(", !RUN %d\n", np->n_state); | |
125 | m_freem(m); | |
126 | goto next; | |
127 | } | |
128 | ||
129 | /* | |
130 | * If this segment is the one after the last | |
131 | * other data segment we acked, and there is | |
132 | * no waiting interrupt message, then queue | |
133 | * this one up. | |
134 | */ | |
135 | if (segnum == SEQ_ADD(np->na_xmtoth, 1) && | |
136 | np->nf_locint == NFL_EMPTY) { | |
137 | if (np->nb_rcv) { | |
138 | printd(", flush old intr data"); | |
139 | m_freem(np->nb_rcv); | |
140 | } | |
141 | if (m->m_len > 16) { | |
142 | printd(", intr data too long\n"); | |
143 | m_freem(m); | |
144 | goto next; | |
145 | } | |
146 | np->nb_rcv = m; | |
147 | np->nf_locint = NFL_INTR; | |
148 | np->na_xmtoth = segnum; /* really += 1 */ | |
149 | np->n_flags |= NF_OTHACK; | |
150 | } else if (SEQ_LEQ(segnum, np->na_xmtoth)) | |
151 | np->n_flags |= NF_OTHACK; | |
152 | break; | |
153 | ||
154 | /* | |
155 | * Got a Link Service message. Process options | |
156 | * to modify flow control values. | |
157 | */ | |
158 | case NSP_LS: | |
159 | printd(", LS"); | |
160 | np = nsp_chkaddr(m, srcnode, NSP_LS, &segnum); | |
161 | if (np == 0) { | |
162 | m_freem(m); | |
163 | goto next; | |
164 | } | |
165 | ||
166 | /* | |
167 | * If we are in the Connect Confirm state then | |
168 | * this Link Service packet causes the transition | |
169 | * to the Run state. Otherwise we better be in | |
170 | * the Run state already. | |
171 | */ | |
172 | if (np->n_state == NS_CC) | |
173 | np->n_state = NS_RUN; | |
174 | else if (np->n_state != NS_RUN) { | |
175 | printd(", !RUN %d\n", np->n_state); | |
176 | m_freem(m); | |
177 | goto next; | |
178 | } | |
179 | p = mtod(m, char *); | |
180 | lsf = *p++; | |
181 | fcval = *p; | |
182 | printd(", lsf 0x%x, fcval %d", lsf, fcval); | |
183 | switch (lsf & NSPLS_FCVALINT) { | |
184 | case NSPLS_DATREQ: | |
185 | if (seqnum == SEQ_ADD(np->na_xmtoth, 1)) { | |
186 | if (np->nf_remdat + fcval >= -128 && | |
187 | np->nf_remdat + fcval <= 127) { | |
188 | np->nf_remdat += fcval; | |
189 | np->na_xmtoth = segnum; | |
190 | np->n_flags |= NF_OTHACK; | |
191 | switch (lsf & NSPLS_FCMOD) { | |
192 | case NSPLS_NOCHANGE: | |
193 | break; | |
194 | case NSPLS_ON: | |
195 | np->n_flags &= ~NF_DATOFF; | |
196 | break; | |
197 | case NSPLS_OFF: | |
198 | np->n_flags |= NF_DATOFF; | |
199 | break; | |
200 | default: | |
201 | printd(", bad fcmod"); | |
202 | } | |
203 | } | |
204 | } else if (SEQ_LEQ(segnum, np->na_xmtoth)) | |
205 | np->n_flags |= NF_OTHACK; | |
206 | break; | |
207 | ||
208 | case NSPLS_INTREQ: | |
209 | if (seqnum == SEQ_ADD(np->na_xmtoth, 1)) { | |
210 | if (fcval >= 0 && np->nf_remint+fcval <= 127) { | |
211 | np->nf_remint += fcval; | |
212 | np->na_xmtoth = segnum; | |
213 | np->n_flags |= NF_OTHACK; | |
214 | } else if (SEQ_LEQ(segnum, np->na_xmtoth)) | |
215 | np->n_flags |= NF_OTHACK; | |
216 | break; | |
217 | ||
218 | default: | |
219 | printd(", bad fcvalint"); | |
220 | } | |
221 | break; | |
222 | ||
223 | /* | |
224 | * Got an acknowledgement for a Data message. | |
225 | * Nsp_chkaddr processes the ack, nothing else | |
226 | * to do. | |
227 | */ | |
228 | case NSP_DATACK: | |
229 | printd(", DATACK"); | |
230 | np = nsp_chkaddr(m, srcnode, NSP_DATACK, &segnum); | |
231 | if (np == 0) { | |
232 | m_freem(m); | |
233 | goto next; | |
234 | } | |
235 | break; | |
236 | ||
237 | /* | |
238 | * Got an acknowledgement for an Other Data message. | |
239 | * Nsp_chkaddr processes the ack, nothing else to do. | |
240 | */ | |
241 | case NSP_OTHACK: | |
242 | printd(", OTHACK"); | |
243 | np = nsp_chkaddr(m, srcnode, NSP_OTHACK, &segnum); | |
244 | if (np == 0) { | |
245 | m_freem(m); | |
246 | goto next; | |
247 | } | |
248 | break; | |
249 | ||
250 | /* | |
251 | * Got a Connect Acknowledgement. Just verify | |
252 | * the address and perform the state transition. | |
253 | */ | |
254 | case NSP_CONACK: | |
255 | DOIT | |
256 | break; | |
257 | ||
258 | /* | |
259 | * Got an unknown message, count it and flush it. | |
260 | */ | |
261 | default: | |
262 | printd(", UNKNOWN!!!"); | |
263 | m_freem(m); | |
264 | break; | |
265 | } | |
266 | printd("\n"); | |
267 | goto next; | |
268 | } |