📄 tcp_subr.pc
字号:
/* * GloMoSim is COPYRIGHTED software. Release 2.02 of GloMoSim is available * at no cost to educational users only. * * Commercial use of this software requires a separate license. No cost, * evaluation licenses are available for such purposes; please contact * info@scalable-networks.com * * By obtaining copies of this and any other files that comprise GloMoSim2.02, * you, the Licensee, agree to abide by the following conditions and * understandings with respect to the copyrighted software: * * 1.Permission to use, copy, and modify this software and its documentation * for education and non-commercial research purposes only is hereby granted * to Licensee, provided that the copyright notice, the original author's * names and unit identification, and this permission notice appear on all * such copies, and that no charge be made for such copies. Any entity * desiring permission to use this software for any commercial or * non-educational research purposes should contact: * * Professor Rajive Bagrodia * University of California, Los Angeles * Department of Computer Science * Box 951596 * 3532 Boelter Hall * Los Angeles, CA 90095-1596 * rajive@cs.ucla.edu * * 2.NO REPRESENTATIONS ARE MADE ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY * PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * * 3.Neither the software developers, the Parallel Computing Lab, UCLA, or any * affiliate of the UC system shall be liable for any damages suffered by * Licensee from the use of this software. */// Use the latest version of Parsec if this line causes a compiler error./* * $Id: tcp_subr.pc,v 1.9 1999/09/28 05:25:20 ktang Exp $ * * Ported from FreeBSD 2.2.2. * This file contains miscellaneous TCP subroutines, eg. initialization. *//* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 * $Id: tcp_subr.pc,v 1.9 1999/09/28 05:25:20 ktang Exp $ */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include "api.h"#include "structmsg.h"#include "tcp.h"#include "transport.h"#include "in_pcb.h"#include "ip.h"#include "tcpip.h"#include "tcp_config.h"#include "tcp_fsm.h"#include "tcp_hdr.h"#include "tcp_proto.h"#include "tcp_seq.h"#include "tcp_timer.h"#include "tcp_var.h"#include "network.h"/* * Remove a node from reassembly queue. */voidremque_ti(node) struct tcpiphdr *node;{ struct tcpiphdr *prev; struct tcpiphdr *next; next = (struct tcpiphdr *)node->ti_next; prev = (struct tcpiphdr *)node->ti_prev; prev->ti_next = (char *) next; next->ti_prev = (char *) prev;} /* * Insert a node just after prev. */voidinsque_ti(node, prev) struct tcpiphdr *node; struct tcpiphdr *prev;{ struct tcpiphdr *next; next = (struct tcpiphdr *)prev->ti_next; node->ti_prev = (char *) prev; node->ti_next = (char *) next; prev->ti_next = (char *) node; next->ti_prev = (char *) node;}/* * Get a new connection id. */int get_conid(head) struct inpcb *head;{ return ++head->con_id;}/* * in_cksum -- * Checksum routine for Internet Protocol family headers (C Version) */intin_cksum(addr, len) unsigned short *addr; int len;{ int nleft = len; unsigned short *w = addr; int sum = 0; unsigned short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer);} /* * Create template to be used to send tcp packets on a connection. * Call after host entry created, allocates an mbuf and fills * in a skeletal tcp/ip header, minimizing the amount of work * necessary when the connection is used. */struct tcpiphdr *tcp_template(tp) struct tcpcb *tp;{ struct inpcb *inp = tp->t_inpcb; struct tcpiphdr *n; if ((n = tp->t_template) == 0) { n = (struct tcpiphdr *)pc_malloc(sizeof(struct tcpiphdr)); } assert (n != NULL); n->ti_next = n->ti_prev = 0; n->ti_x1 = 0; n->ti_pr = IPPROTO_TCP; n->ti_len = sizeof (struct tcpiphdr) - sizeof (struct ip); n->ti_src = inp->inp_local_addr; n->ti_dst = inp->inp_remote_addr; n->ti_sport = inp->inp_local_port; n->ti_dport = inp->inp_remote_port; n->ti_seq = 0; n->ti_ack = 0; n->ti_x2 = 0; n->ti_off = 5; n->ti_flags = 0; n->ti_win = 0; n->ti_sum = 0; n->ti_urp = 0; return (n);}/* * Send a single message to the TCP at address specified by * the given TCP/IP header. If m == 0, then we make a copy * of the tcpiphdr at ti and send directly to the addressed host. * This is used to force keep alive messages out using the TCP * template for a connection tp->t_template. If flags are given * then we send a message back to the TCP which originated the * segment ti, and discard the mbuf containing it and any other * attached mbufs. * * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */voidtcp_respond(node, tp, old_ti, m, ack, seq, flags, tcp_stat) GlomoNode *node; struct tcpcb *tp; struct tcpiphdr *old_ti; tcp_seq ack, seq; int flags, m; struct tcpstat *tcp_stat;{ int win = 0; struct tcpiphdr *ti; struct inpcb *inp = tp->t_inpcb; int priority = inp->priority; Message *msg; if (tcp_stat != NULL) { tcp_stat->tcps_sndtotal++; if (flags & (TH_SYN|TH_FIN|TH_RST)) tcp_stat->tcps_sndctrl++; else if (tp->t_flags & TF_ACKNOW) tcp_stat->tcps_sndacks++; else if (SEQ_GT(tp->snd_up, tp->snd_una)) tcp_stat->tcps_sndurg++; else tcp_stat->tcps_sndwinup++; } if (tp) { win = sbspace(tp->t_inpcb); } msg = GLOMO_MsgAlloc(node, 0, 0, 0); GLOMO_MsgPacketAlloc(node, msg, sizeof(struct tcpiphdr)); ti = (struct tcpiphdr *) msg->packet; assert (ti != NULL); memcpy(ti, old_ti, sizeof(struct tcpiphdr)); if (m == 0) { flags = TH_ACK; } else {#define xchg(a,b,type) { type t; t=a; a=b; b=t; } xchg(ti->ti_dst, ti->ti_src, unsigned long); xchg(ti->ti_dport, ti->ti_sport, unsigned short);#undef xchg } ti->ti_len = (unsigned short)(sizeof (struct tcphdr)); ti->ti_next = ti->ti_prev = 0; ti->ti_x1 = 0; ti->ti_seq = seq; ti->ti_ack = ack; ti->ti_x2 = 0; ti->ti_off = sizeof (struct tcphdr) >> 2; ti->ti_flags = flags; if (tp) ti->ti_win = (unsigned short) (win >> tp->rcv_scale); else ti->ti_win = (unsigned short)win; ti->ti_urp = 0; ti->ti_sum = 0; ti->ti_sum = in_cksum((unsigned short *)ti, sizeof (struct tcpiphdr)); ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr); ((struct ip *)ti)->ip_ttl = IPDEFTTL; /* * Send the packet and remove the extended pseudoheader so that * so that a real IP header can be put on at the IP Layer. */ { NODE_ADDR destinationAddress = ti->ti_dst; GLOMO_MsgRemoveHeader(node, msg, sizeof(struct ipovly)); NetworkIpReceivePacketFromTransportLayer(node, msg, destinationAddress, priority, IPPROTO_TCP, TRANSPORT_DELAY); }}/* * Create a new TCP control block, making an * empty reassembly queue and hooking it to the argument * protocol control block. */struct tcpcb *tcp_newtcpcb(inp) struct inpcb *inp;{ struct tcpcb *tp; tp = (struct tcpcb *)pc_malloc(sizeof(struct tcpcb)); assert(tp != NULL); memset ((char *) tp, 0, sizeof(struct tcpcb)); tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; tp->t_maxseg = tp->t_maxopd = TCP_MSS; /* * Set flags */ if (TCP_DO_RFC1323) tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP); if (TCP_NODELAY) tp->t_flags |= TF_NODELAY; if (TCP_NOOPT) tp->t_flags |= TF_NOOPT; if (TCP_NOPUSH) tp->t_flags |= TF_NOPUSH; tp->t_inpcb = inp; /* * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no * rtt estimate. Set rttvar so that srtt + 4 * rttvar gives * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT)/4; tp->t_rttmin = TCPTV_MIN; tp->t_rxtcur = TCPTV_RTOBASE; tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; inp->inp_ppcb = (char *)tp; return (tp);}/* * Drop a TCP connection. * If connection is synchronized, * then send a RST to peer. */struct tcpcb *tcp_drop(node, tp, tcp_now, tcp_stat) GlomoNode *node; struct tcpcb *tp; unsigned long tcp_now; struct tcpstat *tcp_stat;{ if (TCPS_HAVERCVDSYN(tp->t_state)){ tp->t_state = TCPS_CLOSED; tcp_output(node, tp, tcp_now, tcp_stat); if (tcp_stat) tcp_stat->tcps_drops++; } else { if (tcp_stat) tcp_stat->tcps_conndrops++; } return (tcp_close(node, tp, tcp_stat));}/* * Close a TCP control block: * discard all space held by the tcp * discard internet protocol block * wake up any sleepers */struct tcpcb *tcp_close(node, tp, tcp_stat) GlomoNode *node; struct tcpcb *tp; struct tcpstat *tcp_stat;{ struct tcpiphdr *t, *t1; struct inpcb *inp = tp->t_inpcb; Message *msg; TransportToAppOpenResult *tcpOpenResult; TransportToAppCloseResult *tcpCloseResult; /* free the reassembly queue, if any */ t = tp->seg_next; while (t != (struct tcpiphdr *)tp) { t1 = t; t = (struct tcpiphdr *)t->ti_next; remque_ti(t1); pc_free(t1); } if (tp->t_template) pc_free(tp->t_template); pc_free(tp); inp->inp_ppcb = 0; switch (inp->usrreq){ case INPCB_USRREQ_OPEN: msg = GLOMO_MsgAlloc(node, GLOMO_APP_LAYER, inp->app_proto_type, MSG_APP_FromTransOpenResult); GLOMO_MsgInfoAlloc(node, msg, sizeof(TransportToAppOpenResult)); tcpOpenResult = (TransportToAppOpenResult *) msg->info; tcpOpenResult->type = TCP_CONN_ACTIVE_OPEN; tcpOpenResult->localAddr = inp->inp_local_addr; tcpOpenResult->localPort = inp->inp_local_port; tcpOpenResult->remoteAddr = inp->inp_remote_addr; tcpOpenResult->remotePort = inp->inp_remote_port; tcpOpenResult->connectionId = -1; tcpOpenResult->uniqueId = inp->unique_id; GLOMO_MsgSend(node, msg, TRANSPORT_DELAY); break; case INPCB_USRREQ_CONNECTED: case INPCB_USRREQ_CLOSE: msg = GLOMO_MsgAlloc(node, GLOMO_APP_LAYER, inp->app_proto_type, MSG_APP_FromTransCloseResult); GLOMO_MsgInfoAlloc(node, msg, sizeof(TransportToAppCloseResult)); tcpCloseResult = (TransportToAppCloseResult *) msg->info; if (inp->usrreq == INPCB_USRREQ_CONNECTED) { tcpCloseResult->type = TCP_CONN_PASSIVE_CLOSE; } else { tcpCloseResult->type = TCP_CONN_ACTIVE_CLOSE; } tcpCloseResult->connectionId = inp->con_id; GLOMO_MsgSend(node, msg, TRANSPORT_DELAY); break; case INPCB_USRREQ_NONE: break; default: fprintf(stderr, "TCP: unknown user request %d\n", inp->usrreq); assert(FALSE); } in_pcbdetach(inp); if (tcp_stat) tcp_stat->tcps_closed++; return ((struct tcpcb *)0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -