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