sctp_bsd_addr.c (170094) | sctp_bsd_addr.c (170138) |
---|---|
1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * a) Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. --- 17 unchanged lines hidden (view full) --- 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */ 32 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * a) Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. --- 17 unchanged lines hidden (view full) --- 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 170094 2007-05-29 11:53:27Z rrs $"); | 34__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 170138 2007-05-30 17:39:45Z rrs $"); |
35 36#include <netinet/sctp_os.h> 37#include <netinet/sctp_var.h> 38#include <netinet/sctp_pcb.h> 39#include <netinet/sctp_header.h> 40#include <netinet/sctputil.h> 41#include <netinet/sctp_output.h> 42#include <netinet/sctp_bsd_addr.h> --- 326 unchanged lines hidden (view full) --- 369 } 370#endif 371 return (m); 372} 373 374 375#ifdef SCTP_PACKET_LOGGING 376 | 35 36#include <netinet/sctp_os.h> 37#include <netinet/sctp_var.h> 38#include <netinet/sctp_pcb.h> 39#include <netinet/sctp_header.h> 40#include <netinet/sctputil.h> 41#include <netinet/sctp_output.h> 42#include <netinet/sctp_bsd_addr.h> --- 326 unchanged lines hidden (view full) --- 369 } 370#endif 371 return (m); 372} 373 374 375#ifdef SCTP_PACKET_LOGGING 376 |
377int packet_log_start = 0; | 377int packet_log_writers = 0; |
378int packet_log_end = 0; | 378int packet_log_end = 0; |
379int packet_log_old_end = SCTP_PACKET_LOG_SIZE; 380int packet_log_wrapped = 0; | |
381uint8_t packet_log_buffer[SCTP_PACKET_LOG_SIZE]; 382 383 384void 385sctp_packet_log(struct mbuf *m, int length) 386{ | 379uint8_t packet_log_buffer[SCTP_PACKET_LOG_SIZE]; 380 381 382void 383sctp_packet_log(struct mbuf *m, int length) 384{ |
387 int *lenat, needed, thisone; | 385 int *lenat, thisone; |
388 void *copyto; 389 uint32_t *tick_tock; | 386 void *copyto; 387 uint32_t *tick_tock; |
390 int total_len, spare; | 388 int total_len; 389 int grabbed_lock = 0; 390 int value, newval, thisend, thisbegin; |
391 | 391 |
392 total_len = SCTP_SIZE32((length + (2 * sizeof(int)))); | 392 /* 393 * Buffer layout. -sizeof this entry (total_len) -previous end 394 * (value) -ticks of log (ticks) o -ip packet o -as logged - 395 * where this started (thisbegin) x <--end points here 396 */ 397 total_len = SCTP_SIZE32((length + (4 * sizeof(int)))); |
393 /* Log a packet to the buffer. */ 394 if (total_len > SCTP_PACKET_LOG_SIZE) { 395 /* Can't log this packet I have not a buffer big enough */ 396 return; 397 } 398 if (length < (SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) { | 398 /* Log a packet to the buffer. */ 399 if (total_len > SCTP_PACKET_LOG_SIZE) { 400 /* Can't log this packet I have not a buffer big enough */ 401 return; 402 } 403 if (length < (SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) { |
399 printf("Huh, length is %d to small for sctp min:%d\n", 400 length, 401 (SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))); | |
402 return; 403 } | 404 return; 405 } |
404 SCTP_IP_PKTLOG_LOCK(); 405 if ((SCTP_PACKET_LOG_SIZE - packet_log_end) <= total_len) { 406 /* 407 * it won't fit on the end. We must go back to the 408 * beginning. To do this we go back and cahnge 409 * packet_log_start. 410 */ 411 int orig_end; 412 413 lenat = (int *)packet_log_buffer; 414 orig_end = packet_log_end; 415 packet_log_old_end = packet_log_end; 416 packet_log_end = 0; 417 if (packet_log_start > packet_log_old_end) { 418 /* calculate the head room */ 419 spare = packet_log_start - packet_log_old_end; | 406 atomic_add_int(&packet_log_writers, 1); 407try_again: 408 if (packet_log_writers > SCTP_PKTLOG_WRITERS_NEED_LOCK) { 409 SCTP_IP_PKTLOG_LOCK(); 410 grabbed_lock = 1; 411again_locked: 412 value = packet_log_end; 413 newval = packet_log_end + total_len; 414 if (newval >= SCTP_PACKET_LOG_SIZE) { 415 /* we wrapped */ 416 thisbegin = 0; 417 thisend = total_len; |
420 } else { | 418 } else { |
421 spare = 0; | 419 thisbegin = packet_log_end; 420 thisend = newval; |
422 } | 421 } |
423 needed = total_len - spare; 424 packet_log_wrapped = 1; 425 /* Now update the start */ 426 while (needed > 0) { 427 thisone = (*(int *)(&packet_log_buffer[packet_log_start])); 428 needed -= thisone; 429 if (thisone == 0) { 430 int *foo; 431 432 foo = (int *)(&packet_log_buffer[packet_log_start]); 433 goto insane; 434 } 435 /* move to next one */ 436 packet_log_start += thisone; | 422 if (!(atomic_cmpset_int(&packet_log_end, value, thisend))) { 423 goto again_locked; |
437 } 438 } else { | 424 } 425 } else { |
439 lenat = (int *)&packet_log_buffer[packet_log_end]; 440 if (packet_log_start > packet_log_end) { 441 if ((packet_log_end + total_len) > packet_log_start) { 442 /* Now need to update killing some packets */ 443 needed = total_len - ((packet_log_start - packet_log_end)); 444 while (needed > 0) { 445 thisone = (*(int *)(&packet_log_buffer[packet_log_start])); 446 needed -= thisone; 447 if (thisone == 0) { 448 goto insane; 449 } 450 /* move to next one */ 451 packet_log_start += thisone; 452 if (((packet_log_start + sizeof(struct ip)) > SCTP_PACKET_LOG_SIZE) || 453 (packet_log_wrapped && (packet_log_start >= packet_log_old_end))) { 454 packet_log_start = 0; 455 packet_log_old_end = 0; 456 packet_log_wrapped = 0; 457 break; 458 } 459 } 460 } | 426 value = packet_log_end; 427 newval = packet_log_end + total_len; 428 if (newval >= SCTP_PACKET_LOG_SIZE) { 429 /* we wrapped */ 430 thisbegin = 0; 431 thisend = total_len; 432 } else { 433 thisbegin = packet_log_end; 434 thisend = newval; |
461 } | 435 } |
436 if (!(atomic_cmpset_int(&packet_log_end, value, thisend))) { 437 goto try_again; 438 } |
|
462 } | 439 } |
463 if (((packet_log_end + total_len) >= SCTP_PACKET_LOG_SIZE) || 464 ((void *)((caddr_t)lenat) < (void *)packet_log_buffer) || 465 ((void *)((caddr_t)lenat + total_len) > (void *)&packet_log_buffer[SCTP_PACKET_LOG_SIZE])) { 466 /* Madness protection */ 467insane: 468 printf("Went mad, end:%d start:%d len:%d wrapped:%d oe:%d - zapping\n", 469 packet_log_end, packet_log_start, total_len, packet_log_wrapped, packet_log_old_end); 470 packet_log_start = packet_log_end = packet_log_old_end = packet_log_wrapped = 0; 471 lenat = (int *)&packet_log_buffer[0]; | 440 /* Sanity check */ 441 if (thisend >= SCTP_PACKET_LOG_SIZE) { 442 printf("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n", 443 thisbegin, 444 thisend, 445 packet_log_writers, 446 grabbed_lock, 447 packet_log_end); 448 packet_log_end = 0; 449 goto no_log; 450 |
472 } | 451 } |
452 lenat = (int *)&packet_log_buffer[thisbegin]; |
|
473 *lenat = total_len; 474 lenat++; | 453 *lenat = total_len; 454 lenat++; |
455 *lenat = value; 456 lenat++; |
|
475 tick_tock = (uint32_t *) lenat; 476 lenat++; 477 *tick_tock = sctp_get_tick_count(); 478 copyto = (void *)lenat; | 457 tick_tock = (uint32_t *) lenat; 458 lenat++; 459 *tick_tock = sctp_get_tick_count(); 460 copyto = (void *)lenat; |
479 packet_log_end = (((caddr_t)copyto + length) - (caddr_t)packet_log_buffer); 480 SCTP_IP_PKTLOG_UNLOCK(); | 461 thisone = thisend - sizeof(int); 462 lenat = (int *)&packet_log_buffer[thisone]; 463 *lenat = thisbegin; 464 if (grabbed_lock) { 465 SCTP_IP_PKTLOG_UNLOCK(); 466 grabbed_lock = 0; 467 } |
481 m_copydata(m, 0, length, (caddr_t)copyto); | 468 m_copydata(m, 0, length, (caddr_t)copyto); |
482 | 469no_log: 470 if (grabbed_lock) { 471 SCTP_IP_PKTLOG_UNLOCK(); 472 } 473 atomic_subtract_int(&packet_log_writers, 1); |
483} 484 485 486int 487sctp_copy_out_packet_log(uint8_t * target, int length) 488{ 489 /* 490 * We wind through the packet log starting at start copying up to 491 * length bytes out. We return the number of bytes copied. 492 */ | 474} 475 476 477int 478sctp_copy_out_packet_log(uint8_t * target, int length) 479{ 480 /* 481 * We wind through the packet log starting at start copying up to 482 * length bytes out. We return the number of bytes copied. 483 */ |
493 int tocopy, this_copy, copied = 0; 494 void *at; | 484 int tocopy, this_copy; 485 int *lenat; 486 int did_delay = 0; |
495 496 tocopy = length; | 487 488 tocopy = length; |
497 if (packet_log_start == packet_log_end) { 498 /* no data */ | 489 if (length < (2 * sizeof(int))) { 490 /* not enough room */ |
499 return (0); 500 } | 491 return (0); 492 } |
501 if (packet_log_wrapped) { 502 /* 503 * we have a wrapped buffer, we must copy from start to the 504 * old end. Then copy from the top of the buffer to the end. 505 */ 506 SCTP_IP_PKTLOG_LOCK(); 507 at = (void *)&packet_log_buffer[packet_log_start]; 508 this_copy = min(tocopy, (packet_log_old_end - packet_log_start)); 509 memcpy(target, at, this_copy); 510 tocopy -= this_copy; 511 copied += this_copy; 512 if (tocopy == 0) { 513 SCTP_IP_PKTLOG_UNLOCK(); 514 return (copied); | 493 if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 494 atomic_add_int(&packet_log_writers, SCTP_PKTLOG_WRITERS_NEED_LOCK); 495again: 496 if ((did_delay == 0) && (packet_log_writers != SCTP_PKTLOG_WRITERS_NEED_LOCK)) { 497 /* 498 * we delay here for just a moment hoping the 499 * writer(s) that were present when we entered will 500 * have left and we only have locking ones that will 501 * contend with us for the lock. This does not 502 * assure 100% access, but its good enough for a 503 * logging facility like this. 504 */ 505 did_delay = 1; 506 DELAY(10); 507 goto again; |
515 } | 508 } |
516 this_copy = min(tocopy, packet_log_end); 517 at = (void *)&packet_log_buffer; 518 memcpy(&target[copied], at, this_copy); 519 copied += this_copy; 520 SCTP_IP_PKTLOG_UNLOCK(); 521 return (copied); 522 } else { 523 /* we have one contiguous buffer */ 524 SCTP_IP_PKTLOG_LOCK(); 525 at = (void *)&packet_log_buffer; 526 this_copy = min(length, packet_log_end); 527 memcpy(target, at, this_copy); 528 SCTP_IP_PKTLOG_UNLOCK(); 529 return (this_copy); | |
530 } | 509 } |
510 SCTP_IP_PKTLOG_LOCK(); 511 lenat = (int *)target; 512 *lenat = packet_log_end; 513 lenat++; 514 this_copy = min((length - sizeof(int)), packet_log_end); 515 memcpy((void *)lenat, (void *)packet_log_buffer, this_copy); 516 if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 517 atomic_subtract_int(&packet_log_writers, SCTP_PKTLOG_WRITERS_NEED_LOCK); 518 } 519 SCTP_IP_PKTLOG_UNLOCK(); 520 return (this_copy + sizeof(int)); |
|
531} 532 533#endif | 521} 522 523#endif |