Changeset 0edaf0f6 in mainline
- Timestamp:
- 2011-12-16T18:04:30Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ab9378b4
- Parents:
- 7a8c1c4e
- Location:
- uspace/srv/net/tl/tcp
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/tcp/conn.c
r7a8c1c4e r0edaf0f6 56 56 57 57 LIST_INITIALIZE(conn_list); 58 FIBRIL_MUTEX_INITIALIZE(conn_list_lock); 58 59 59 60 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg); … … 81 82 goto error; 82 83 84 fibril_mutex_initialize(&conn->lock); 85 86 /* One for the user, one for not being in closed state */ 87 atomic_set(&conn->refcnt, 2); 88 83 89 /* Allocate receive buffer */ 84 fibril_mutex_initialize(&conn->rcv_buf_lock);85 90 fibril_condvar_initialize(&conn->rcv_buf_cv); 86 91 conn->rcv_buf_size = RCV_BUF_SIZE; … … 93 98 94 99 /** Allocate send buffer */ 95 fibril_mutex_initialize(&conn->snd_buf_lock);96 100 fibril_condvar_initialize(&conn->snd_buf_cv); 97 101 conn->snd_buf_size = SND_BUF_SIZE; … … 115 119 116 120 /* Connection state change signalling */ 117 fibril_mutex_initialize(&conn->cstate_lock);118 121 fibril_condvar_initialize(&conn->cstate_cv); 119 122 … … 146 149 /** Destroy connection structure. 147 150 * 148 * Connection structure should be destroyed when both of two conditions are 149 * met: (1) user has deleted the connection and (2) the connection has entered 150 * closed state. 151 * Connection structure should be destroyed when the folowing condtitions 152 * are met: 153 * (1) user has deleted the connection 154 * (2) the connection has entered closed state 155 * (3) nobody is holding references to the connection 156 * 157 * This happens when @a conn->refcnt is zero as we count (1) and (2) 158 * as special references. 151 159 * 152 160 * @param conn Connection … … 166 174 } 167 175 176 /** Add reference to connection. 177 * 178 * Increase connection reference count by one. 179 * 180 * @param conn Connection 181 */ 182 void tcp_conn_addref(tcp_conn_t *conn) 183 { 184 log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn); 185 atomic_inc(&conn->refcnt); 186 } 187 188 /** Remove reference from connection. 189 * 190 * Decrease connection reference count by one. 191 * 192 * @param conn Connection 193 */ 194 void tcp_conn_delref(tcp_conn_t *conn) 195 { 196 log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn); 197 198 if (atomic_predec(&conn->refcnt) == 0) 199 tcp_conn_free(conn); 200 } 201 168 202 /** Delete connection. 169 203 * … … 175 209 void tcp_conn_delete(tcp_conn_t *conn) 176 210 { 177 fibril_mutex_lock(&conn->cstate_lock); 178 conn->deleted = true; 179 180 if (conn->cstate == st_closed) { 181 fibril_mutex_unlock(&conn->cstate_lock); 182 tcp_conn_free(conn); 183 } else { 184 fibril_mutex_unlock(&conn->cstate_lock); 185 } 211 log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn); 212 213 assert(conn->deleted == false); 214 tcp_conn_delref(conn); 186 215 } 187 216 … … 192 221 void tcp_conn_add(tcp_conn_t *conn) 193 222 { 223 fibril_mutex_lock(&conn_list_lock); 194 224 list_append(&conn->link, &conn_list); 225 fibril_mutex_unlock(&conn_list_lock); 195 226 } 196 227 … … 201 232 void tcp_conn_remove(tcp_conn_t *conn) 202 233 { 234 fibril_mutex_lock(&conn_list_lock); 203 235 list_remove(&conn->link); 236 fibril_mutex_unlock(&conn_list_lock); 204 237 } 205 238 206 239 static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate) 207 240 { 208 fibril_mutex_lock(&conn->cstate_lock); 241 tcp_cstate_t old_state; 242 243 old_state = conn->cstate; 209 244 conn->cstate = nstate; 210 245 fibril_condvar_broadcast(&conn->cstate_cv); 211 246 212 if (nstate == st_closed && conn->deleted) { 213 fibril_mutex_unlock(&conn->cstate_lock); 214 tcp_conn_free(conn); 215 } else { 216 fibril_mutex_unlock(&conn->cstate_lock); 247 assert(old_state != st_closed); 248 if (nstate == st_closed) { 249 /* Drop one reference for now being in closed state */ 250 tcp_conn_delref(conn); 217 251 } 218 252 } … … 302 336 * A connection is uniquely identified by a socket pair. Look up our 303 337 * connection map and return connection structure based on socket pair. 338 * The connection reference count is bumped by one. 304 339 * 305 340 * @param sp Socket pair 306 341 * @return Connection structure or NULL if not found. 307 342 */ 308 tcp_conn_t *tcp_conn_find (tcp_sockpair_t *sp)343 tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp) 309 344 { 310 345 log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp); 346 347 fibril_mutex_lock(&conn_list_lock); 311 348 312 349 list_foreach(conn_list, link) { … … 317 354 csp->local.addr.ipv4, csp->local.port); 318 355 if (tcp_sockpair_match(sp, csp)) { 356 tcp_conn_addref(conn); 357 fibril_mutex_unlock(&conn_list_lock); 319 358 return conn; 320 359 } 321 360 } 322 361 362 fibril_mutex_unlock(&conn_list_lock); 323 363 return NULL; 324 364 } … … 910 950 tcp_conn_trim_seg_to_wnd(conn, seg); 911 951 912 fibril_mutex_lock(&conn->rcv_buf_lock);913 914 952 /* Determine how many bytes to copy */ 915 953 text_size = tcp_segment_text_size(seg); … … 923 961 /* Signal to the receive function that new data has arrived */ 924 962 fibril_condvar_broadcast(&conn->rcv_buf_cv); 925 fibril_mutex_unlock(&conn->rcv_buf_lock);926 963 927 964 log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size); … … 1013 1050 1014 1051 /* Add FIN to the receive buffer */ 1015 fibril_mutex_lock(&conn->rcv_buf_lock);1016 1052 conn->rcv_buf_fin = true; 1017 1053 fibril_condvar_broadcast(&conn->rcv_buf_cv); 1018 fibril_mutex_unlock(&conn->rcv_buf_lock);1019 1054 1020 1055 tcp_segment_delete(seg); … … 1125 1160 log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn); 1126 1161 1162 fibril_mutex_lock(&conn->lock); 1163 1127 1164 if (conn->cstate == st_closed) { 1128 1165 log_msg(LVL_DEBUG, "Connection already closed."); 1166 fibril_mutex_unlock(&conn->lock); 1167 tcp_conn_delref(conn); 1129 1168 return; 1130 1169 } … … 1133 1172 tcp_conn_remove(conn); 1134 1173 tcp_conn_state_set(conn, st_closed); 1174 1175 fibril_mutex_unlock(&conn->lock); 1176 tcp_conn_delref(conn); 1135 1177 } 1136 1178 … … 1141 1183 void tcp_conn_tw_timer_set(tcp_conn_t *conn) 1142 1184 { 1185 tcp_conn_addref(conn); 1143 1186 fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func, 1144 1187 (void *)conn); … … 1151 1194 void tcp_conn_tw_timer_clear(tcp_conn_t *conn) 1152 1195 { 1153 fibril_timer_clear(conn->tw_timer); 1196 if (fibril_timer_clear(conn->tw_timer) == fts_active) 1197 tcp_conn_delref(conn); 1154 1198 } 1155 1199 -
uspace/srv/net/tl/tcp/conn.h
r7a8c1c4e r0edaf0f6 46 46 extern void tcp_conn_fin_sent(tcp_conn_t *); 47 47 extern void tcp_conn_ack_of_fin_rcvd(tcp_conn_t *); 48 extern tcp_conn_t *tcp_conn_find(tcp_sockpair_t *); 48 extern tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *); 49 extern void tcp_conn_addref(tcp_conn_t *); 50 extern void tcp_conn_delref(tcp_conn_t *); 49 51 extern bool tcp_conn_got_syn(tcp_conn_t *); 50 52 extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *); -
uspace/srv/net/tl/tcp/tcp_type.h
r7a8c1c4e r0edaf0f6 162 162 acpass_t ap; 163 163 164 /** Protects access to connection structure */ 165 fibril_mutex_t lock; 166 /** Reference count */ 167 atomic_t refcnt; 168 164 169 /** Connection state */ 165 170 tcp_cstate_t cstate; … … 168 173 /** True if connection was deleted by user */ 169 174 bool deleted; 170 /** Protects @c cstate */171 fibril_mutex_t cstate_lock;172 175 /** Signalled when @c cstate changes */ 173 176 fibril_condvar_t cstate_cv; … … 193 196 /** Receive buffer contains FIN */ 194 197 bool rcv_buf_fin; 195 /** Receive buffer lock */196 fibril_mutex_t rcv_buf_lock;197 198 /** Receive buffer CV. Broadcast when new data is inserted */ 198 199 fibril_condvar_t rcv_buf_cv; … … 206 207 /** Send buffer contains FIN */ 207 208 bool snd_buf_fin; 208 /** Send buffer lock */209 fibril_mutex_t snd_buf_lock;210 209 /** Send buffer CV. Broadcast when space is made available in buffer */ 211 210 fibril_condvar_t snd_buf_cv; -
uspace/srv/net/tl/tcp/tqueue.c
r7a8c1c4e r0edaf0f6 167 167 log_msg(LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name); 168 168 169 fibril_mutex_lock(&conn->snd_buf_lock);170 171 169 /* Number of free sequence numbers in send window */ 172 170 avail_wnd = (conn->snd_una + conn->snd_wnd) - conn->snd_nxt; … … 178 176 xfer_seqlen); 179 177 180 if (xfer_seqlen == 0) { 181 fibril_mutex_unlock(&conn->snd_buf_lock); 182 return; 183 } 178 if (xfer_seqlen == 0) 179 return; 184 180 185 181 /* XXX Do not always send immediately */ … … 198 194 seg = tcp_segment_make_data(ctrl, conn->snd_buf, data_size); 199 195 if (seg == NULL) { 200 fibril_mutex_unlock(&conn->snd_buf_lock);201 196 log_msg(LVL_ERROR, "Memory allocation failure."); 202 197 return; … … 212 207 213 208 fibril_condvar_broadcast(&conn->snd_buf_cv); 214 fibril_mutex_unlock(&conn->snd_buf_lock);215 209 216 210 if (send_fin) … … 323 317 log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn); 324 318 319 fibril_mutex_lock(&conn->lock); 320 325 321 if (conn->cstate == st_closed) { 326 322 log_msg(LVL_DEBUG, "Connection already closed."); 323 fibril_mutex_unlock(&conn->lock); 324 tcp_conn_delref(conn); 327 325 return; 328 326 } … … 331 329 if (link == NULL) { 332 330 log_msg(LVL_DEBUG, "Nothing to retransmit"); 331 fibril_mutex_unlock(&conn->lock); 332 tcp_conn_delref(conn); 333 333 return; 334 334 } … … 339 339 if (rt_seg == NULL) { 340 340 log_msg(LVL_ERROR, "Memory allocation failed."); 341 fibril_mutex_unlock(&conn->lock); 342 tcp_conn_delref(conn); 341 343 /* XXX Handle properly */ 342 344 return; … … 348 350 /* Reset retransmission timer */ 349 351 tcp_tqueue_timer_set(tqe->conn); 352 353 fibril_mutex_unlock(&conn->lock); 354 tcp_conn_delref(conn); 350 355 } 351 356 … … 355 360 log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name); 356 361 357 (void) retransmit_timeout_func; 362 /* Clear first to make sure we update refcnt correctly */ 363 tcp_tqueue_timer_clear(conn); 364 365 tcp_conn_addref(conn); 358 366 fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT, 359 367 retransmit_timeout_func, (void *) conn); … … 365 373 log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name); 366 374 367 fibril_timer_clear(conn->retransmit.timer); 375 if (fibril_timer_clear(conn->retransmit.timer) == fts_active) 376 tcp_conn_delref(conn); 368 377 } 369 378 -
uspace/srv/net/tl/tcp/ucall.c
r7a8c1c4e r0edaf0f6 83 83 /* Wait for connection to be established or reset */ 84 84 log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection."); 85 fibril_mutex_lock(&nconn-> cstate_lock);85 fibril_mutex_lock(&nconn->lock); 86 86 while (nconn->cstate == st_listen || 87 87 nconn->cstate == st_syn_sent || 88 88 nconn->cstate == st_syn_received) { 89 fibril_condvar_wait(&nconn->cstate_cv, &nconn-> cstate_lock);89 fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock); 90 90 } 91 91 … … 93 93 log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset."); 94 94 assert(nconn->cstate == st_closed); 95 fibril_mutex_unlock(&nconn-> cstate_lock);95 fibril_mutex_unlock(&nconn->lock); 96 96 return TCP_ERESET; 97 97 } 98 98 99 fibril_mutex_unlock(&nconn-> cstate_lock);99 fibril_mutex_unlock(&nconn->lock); 100 100 log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established."); 101 101 … … 113 113 log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name); 114 114 115 if (conn->cstate == st_closed) 115 fibril_mutex_lock(&conn->lock); 116 117 if (conn->cstate == st_closed) { 118 fibril_mutex_unlock(&conn->lock); 116 119 return TCP_ENOTEXIST; 120 } 117 121 118 122 if (conn->cstate == st_listen) { … … 121 125 } 122 126 123 fibril_mutex_lock(&conn->snd_buf_lock);124 127 125 128 if (conn->snd_buf_fin) { 126 fibril_mutex_unlock(&conn-> snd_buf_lock);129 fibril_mutex_unlock(&conn->lock); 127 130 return TCP_ECLOSING; 128 131 } … … 133 136 log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.", 134 137 conn->name); 135 fibril_condvar_wait(&conn->snd_buf_cv, 136 &conn->snd_buf_lock); 138 fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock); 137 139 buf_free = conn->snd_buf_size - conn->snd_buf_used; 138 140 } 139 141 140 142 if (conn->reset) { 141 fibril_mutex_unlock(&conn-> snd_buf_lock);143 fibril_mutex_unlock(&conn->lock); 142 144 return TCP_ERESET; 143 145 } … … 151 153 size -= xfer_size; 152 154 153 fibril_mutex_unlock(&conn->snd_buf_lock);154 155 tcp_tqueue_new_data(conn); 155 fibril_mutex_lock(&conn->snd_buf_lock); 156 } 157 158 fibril_mutex_unlock(&conn->snd_buf_lock); 156 } 157 159 158 tcp_tqueue_new_data(conn); 159 fibril_mutex_unlock(&conn->lock); 160 160 161 161 return TCP_EOK; … … 170 170 log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name); 171 171 172 if (conn->cstate == st_closed) 172 fibril_mutex_lock(&conn->lock); 173 174 if (conn->cstate == st_closed) { 175 fibril_mutex_unlock(&conn->lock); 173 176 return TCP_ENOTEXIST; 174 175 fibril_mutex_lock(&conn->rcv_buf_lock); 177 } 176 178 177 179 /* Wait for data to become available */ 178 180 while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) { 179 181 log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data"); 180 fibril_condvar_wait(&conn->rcv_buf_cv, &conn-> rcv_buf_lock);182 fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock); 181 183 } 182 184 183 185 if (conn->rcv_buf_used == 0) { 184 fibril_mutex_unlock(&conn->rcv_buf_lock);185 186 186 *rcvd = 0; 187 187 *xflags = 0; … … 189 189 if (conn->rcv_buf_fin) { 190 190 /* End of data, peer closed connection */ 191 fibril_mutex_unlock(&conn->lock); 191 192 return TCP_ECLOSING; 192 193 } else { 193 194 /* Connection was reset */ 194 195 assert(conn->reset); 196 fibril_mutex_unlock(&conn->lock); 195 197 return TCP_ERESET; 196 198 } … … 208 210 conn->rcv_wnd += xfer_size; 209 211 210 fibril_mutex_unlock(&conn->rcv_buf_lock);211 212 212 /* TODO */ 213 213 *xflags = 0; … … 219 219 conn->name, xfer_size); 220 220 221 fibril_mutex_unlock(&conn->lock); 222 221 223 return TCP_EOK; 222 224 } … … 227 229 log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name); 228 230 229 if (conn->cstate == st_closed) 231 fibril_mutex_lock(&conn->lock); 232 233 if (conn->cstate == st_closed) { 234 fibril_mutex_unlock(&conn->lock); 230 235 return TCP_ENOTEXIST; 231 232 if (conn->snd_buf_fin) 236 } 237 238 if (conn->snd_buf_fin) { 239 fibril_mutex_unlock(&conn->lock); 233 240 return TCP_ECLOSING; 241 } 234 242 235 243 conn->snd_buf_fin = true; 236 244 tcp_tqueue_new_data(conn); 237 245 246 fibril_mutex_unlock(&conn->lock); 238 247 return TCP_EOK; 239 248 } … … 276 285 sp->local.addr.ipv4, sp->local.port); 277 286 278 conn = tcp_conn_find(sp); 279 if (conn != NULL && conn->cstate != st_closed) { 280 if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY) 281 conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4; 282 if (conn->ident.foreign.port == TCP_PORT_ANY) 283 conn->ident.foreign.port = sp->foreign.port; 284 if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY) 285 conn->ident.local.addr.ipv4 = sp->local.addr.ipv4; 286 287 tcp_conn_segment_arrived(conn, seg); 288 } else { 289 if (conn == NULL) 290 log_msg(LVL_WARN, "No connection found."); 291 else 292 log_msg(LVL_WARN, "Connection is closed."); 287 conn = tcp_conn_find_ref(sp); 288 if (conn == NULL) { 289 log_msg(LVL_WARN, "No connection found."); 293 290 tcp_unexpected_segment(sp, seg); 294 } 291 return; 292 } 293 294 fibril_mutex_lock(&conn->lock); 295 296 if (conn->cstate == st_closed) { 297 log_msg(LVL_WARN, "Connection is closed."); 298 tcp_unexpected_segment(sp, seg); 299 fibril_mutex_unlock(&conn->lock); 300 tcp_conn_delref(conn); 301 return; 302 } 303 304 if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY) 305 conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4; 306 if (conn->ident.foreign.port == TCP_PORT_ANY) 307 conn->ident.foreign.port = sp->foreign.port; 308 if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY) 309 conn->ident.local.addr.ipv4 = sp->local.addr.ipv4; 310 311 tcp_conn_segment_arrived(conn, seg); 312 313 fibril_mutex_unlock(&conn->lock); 314 tcp_conn_delref(conn); 295 315 } 296 316
Note:
See TracChangeset
for help on using the changeset viewer.