xref: /csrg-svn/sys/deprecated/bbnnet/macros.h (revision 25202)
1*25202Skarels 
2*25202Skarels 	/*** macros to simulate action() ***/
3*25202Skarels 
4*25202Skarels extern int tcprint;
5*25202Skarels 
6*25202Skarels #define TCP_DEBUG(soptr,tptr,wptr,act,newstate) \
7*25202Skarels 	if (soptr){ \
8*25202Skarels 		if ((soptr)->so_options & SO_DEBUG) { \
9*25202Skarels 			if (tcprint) \
10*25202Skarels 				printf("via 0x%x, ", fsactab[act]); \
11*25202Skarels 			tcp_debug(tptr, wptr, newstate); \
12*25202Skarels 		} \
13*25202Skarels 	}
14*25202Skarels 
15*25202Skarels 
16*25202Skarels /*
17*25202Skarels  * Simulates calls to action.
18*25202Skarels  *	tp	valid tcpcb pointer ( == wp->w_tcb )
19*25202Skarels  *	so	valid socket pointer ( == tp->t_in_pcb->inp_socket )
20*25202Skarels  *	wp	valid work pointer
21*25202Skarels  *	wtype	== wp->w_type, used so compiler can remove constant conditionals
22*25202Skarels  *	wdat	== wp->w_dat
23*25202Skarels  *
24*25202Skarels  *	act, newstate	integers
25*25202Skarels  *
26*25202Skarels  * Remember that if the state transition results in CLOSED, then we have
27*25202Skarels  * lost the mbuf(s) containing the tcpcb...
28*25202Skarels  *
29*25202Skarels  * moved tcp->net_keep to tcp_net_keep to avoid race condition since don't
30*25202Skarels  * always have MBUF holding tcp after state transition function returns.
31*25202Skarels  */
32*25202Skarels extern int tcp_net_keep;
33*25202Skarels 
34*25202Skarels #define ACTION(tp, so, wp, wtype, wdat, act, newstate) \
35*25202Skarels {	act = fstab[(tp)->t_state][wtype]; \
36*25202Skarels 	if (act == 0)  { \
37*25202Skarels 		/* \
38*25202Skarels 		 * invalid state transition, just print a message and ignore \
39*25202Skarels 		 */ \
40*25202Skarels 		printf("tcp bad state: tcb=%x state=%d input=%d\n", \
41*25202Skarels 			tp, (tp)->t_state, wtype); \
42*25202Skarels 		if (wdat != NULL && wtype == INRECV) \
43*25202Skarels 			m_freem(dtom(wdat)); \
44*25202Skarels 	} else { \
45*25202Skarels 		tcp_net_keep = FALSE; \
46*25202Skarels 		newstate = (*fsactab[act])(wp); \
47*25202Skarels 		TCP_DEBUG (so, tp, wp, act, newstate); \
48*25202Skarels 		if (wdat != NULL && !tcp_net_keep && wtype == INRECV) \
49*25202Skarels 			m_freem(dtom(wdat)); \
50*25202Skarels 		if ((newstate != SAME) && (newstate != CLOSED)) \
51*25202Skarels 			(tp)->t_state = newstate; \
52*25202Skarels 	} \
53*25202Skarels }
54*25202Skarels 
55*25202Skarels extern char	fstab[TCP_NSTATES][INOP];
56*25202Skarels extern int	(*fsactab[])();
57*25202Skarels 
58*25202Skarels /*
59*25202Skarels  * like w_alloc() macro, but suitable for above ACTION.
60*25202Skarels  */
61*25202Skarels #define W_ALLOC(type, stype, tp, m, so, act, newstate) \
62*25202Skarels {									\
63*25202Skarels 	struct work w; \
64*25202Skarels 	w.w_type = type; w.w_stype = stype; w.w_tcb = tp; w.w_dat = (char *)m; \
65*25202Skarels 	ACTION(tp, so, &w, type, m, act, newstate); \
66*25202Skarels }
67*25202Skarels 
68*25202Skarels 
69*25202Skarels /*
70*25202Skarels  * Enqueue/dequeue segment on tcp sequencing queue
71*25202Skarels  */
72*25202Skarels #define TCP_ENQ(new, list, tp) \
73*25202Skarels {	(tp)->t_rcv_len += (new)->t_len; \
74*25202Skarels 	insque(new, list); \
75*25202Skarels }
76*25202Skarels 
77*25202Skarels #define TCP_DEQ(old, tp) \
78*25202Skarels {	(tp)->t_rcv_len -= (old)->t_len; \
79*25202Skarels 	remque(old); \
80*25202Skarels }
81*25202Skarels 
82*25202Skarels /*
83*25202Skarels  * Macro form of firstempty().  Find the first empty spot in rcv buffer.
84*25202Skarels  */
85*25202Skarels #define FIRSTEMPTY(tp, retval) \
86*25202Skarels {	register struct th *p; \
87*25202Skarels  \
88*25202Skarels 	if ((p = (tp)->t_rcv_next) == (struct th *)(tp) || \
89*25202Skarels 	    SEQ_LT((tp)->rcv_nxt, p->t_seq)) \
90*25202Skarels 		retval = (tp)->rcv_nxt; \
91*25202Skarels 	else { \
92*25202Skarels 		register struct th *q; \
93*25202Skarels  \
94*25202Skarels 		while ((q = p->t_next) != (struct th *)(tp) && \
95*25202Skarels 		       SEQ_EQ(t_end(p)+1, q->t_seq)) \
96*25202Skarels 			p = q; \
97*25202Skarels  \
98*25202Skarels 		retval = t_end(p) + 1; \
99*25202Skarels 	}}
100*25202Skarels 
101*25202Skarels /*
102*25202Skarels  * macro form of present_data().
103*25202Skarels  */
104*25202Skarels extern struct mbuf *extract_oob();
105*25202Skarels 
106*25202Skarels #define PRESENT_DATA(tp) \
107*25202Skarels { \
108*25202Skarels 	/* connection must be synced and data available for user */ \
109*25202Skarels  \
110*25202Skarels 	if ((tp)->syn_acked){ \
111*25202Skarels 		register struct th *t; \
112*25202Skarels 			 struct socket *so; \
113*25202Skarels  \
114*25202Skarels 		so = (tp)->t_in_pcb->inp_socket; \
115*25202Skarels 		if ((t = (tp)->t_rcv_next) != (struct th *)(tp)) { \
116*25202Skarels 		    /* \
117*25202Skarels 		     * move as many mbufs as possible from tcb \
118*25202Skarels 		     * to user queue.  Used to use firstempty(), \
119*25202Skarels 		     * but that caused traversal of list twice. \
120*25202Skarels 		     */ \
121*25202Skarels 		    if (SEQ_LEQ(t->t_seq, (tp)->rcv_nxt)) { \
122*25202Skarels 		        register struct sockbuf *sorcv; \
123*25202Skarels 			register int	done; \
124*25202Skarels 			register struct mbuf *m; \
125*25202Skarels 			register struct th *next; \
126*25202Skarels  \
127*25202Skarels 		        sorcv = &so->so_rcv; \
128*25202Skarels 			done = FALSE; \
129*25202Skarels 			while (sbspace(sorcv) > 0 && !done) { \
130*25202Skarels 				/* \
131*25202Skarels 				 * Note order of events: sbappend tries to \
132*25202Skarels 				 * coalesce mbufs, so if get a packet in, it \
133*25202Skarels 				 * may use the mbuf that sbappend may free. \
134*25202Skarels 				 */ \
135*25202Skarels  \
136*25202Skarels 				/* dequeue chunk from tcb */ \
137*25202Skarels  \
138*25202Skarels 				next = t->t_next; \
139*25202Skarels 				TCP_DEQ(t, tp); \
140*25202Skarels 				m = dtom(t); \
141*25202Skarels  \
142*25202Skarels 				/* \
143*25202Skarels 				 * check for end of list and gaps. \
144*25202Skarels 				 */ \
145*25202Skarels 				if ((next == (struct th *)tp) || \
146*25202Skarels 				    (t_end(t)+1 != next->t_seq)) \
147*25202Skarels 					done = TRUE; \
148*25202Skarels  \
149*25202Skarels 				/* SS_CANTRCVMORE == usr_abort */  \
150*25202Skarels 				if (so->so_state & SS_CANTRCVMORE) \
151*25202Skarels 					m_freem(m); \
152*25202Skarels 				else { \
153*25202Skarels 					/* \
154*25202Skarels 					 * remove urgent data from input stream\
155*25202Skarels 					 */ \
156*25202Skarels 					if (SEQ_GEQ((tp)->rcv_urpend, (tp)->rcv_urp)) \
157*25202Skarels 						m = extract_oob(tp, m, sorcv); \
158*25202Skarels  \
159*25202Skarels 					if (m) \
160*25202Skarels 						/* \
161*25202Skarels 						 * chain new data to user \
162*25202Skarels 						 * receive buf \
163*25202Skarels 						 */ \
164*25202Skarels 						sbappend(sorcv, m); \
165*25202Skarels 				} \
166*25202Skarels  \
167*25202Skarels 				t = next; \
168*25202Skarels 			} \
169*25202Skarels  \
170*25202Skarels 		        /* awaken reader only if any data on user rcv queue */ \
171*25202Skarels 		        if (sorcv->sb_cc > 0) \
172*25202Skarels 				sbwakeup(sorcv); \
173*25202Skarels 		    } \
174*25202Skarels 		} \
175*25202Skarels  \
176*25202Skarels 		/* let user know about foreign tcp close if no more data \
177*25202Skarels 		 * OR if no data ever transferred. \
178*25202Skarels 		 */ \
179*25202Skarels  \
180*25202Skarels 		if ((tp)->fin_rcvd && /* !tp->usr_closed && */ rcv_empty(tp)) \
181*25202Skarels 			socantrcvmore(so); \
182*25202Skarels 	}}
183