⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snooptcp.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 2 页
字号:
  else if (ack == _mh_last_ack && datalen == 0)    // duplicate ack w/o data    // (duplicate acks with data are not semantically "duplicate acks")    p = mh_dup_ack(p, tcph, ack);    else if (SEQ_LT(ack, _mh_last_ack))    // spurious ack: ignore    return p;    _mh_last_win = ntohs(tcph->th_win);  return p;}voidSnoopTCP::PCB::mh_data(Packet *, const click_tcp *tcph, int datalen){  // initialize connection (starting up snoop in the middle of a connection)  // or mark it alive  if (datalen) {    if (!_mh_exists)      initialize(false, tcph, datalen);    else      _mh_alive = true;  }  // XXX rest}SnoopTCP::PCB *SnoopTCP::find(unsigned s_ip, unsigned short s_port,	       unsigned int mh_ip, unsigned short mh_port, bool create){  IPFlowID q(s_ip, s_port, mh_ip, mh_port);    if (PCB **pcbp = _map.findp(q))    return *pcbp;  else if (create) {    PCB *pcb = new PCB();    if (pcb) _map.insert(q, pcb);    return pcb;  } else    return 0;}Packet *SnoopTCP::handle_packet(int port, Packet *p){  const click_ip *iph = p->ip_header();  if (p->length() < 40 || iph->ip_p != IPPROTO_TCP) {    DEBUG_CHATTER("Non TCP");    // ignore non-TCP traffic    return p;  }    const click_tcp *tcph = p->tcp_header();  int header_len = (iph->ip_hl << 2) + (tcph->th_off << 2);  int datalen = p->length() - header_len;    // get or create corresponding PCB  // don't create a PCB for packets w/o data  PCB *pcb;  if (port == 0)    pcb = find(iph->ip_src.s_addr, tcph->th_sport,	       iph->ip_dst.s_addr, tcph->th_dport, datalen > 0);  else    pcb = find(iph->ip_dst.s_addr, tcph->th_dport,	       iph->ip_src.s_addr, tcph->th_sport, datalen > 0);  if (!pcb)    // out of space, could not create PCB    return p;    // SYN flag: initialize that side of the connection  if (tcph->th_flags & TH_SYN) {    DEBUG_CHATTER("SYN packet");    pcb->clear(port == 0);    pcb->initialize(port == 0, tcph, datalen);    return p;  }    // FIN or RST: kill that side of the connection  if (tcph->th_flags & (TH_FIN | TH_RST)) {    pcb->clear(port == 0);    return p;  }    if (port == 0) {    if (tcph->th_flags & TH_ACK)      pcb->s_ack(p, tcph, datalen);    if (datalen > 0)      p = pcb->s_data(p, tcph, datalen);      } else {    if (tcph->th_flags & TH_ACK)      p = pcb->mh_ack(p, tcph, datalen);    if (datalen > 0)      pcb->mh_data(p, tcph, datalen);  }    return p;}voidSnoopTCP::push(int port, Packet *p){  p = handle_packet(port, p);  if (p) output(port).push(p);}Packet *SnoopTCP::pull(int port){  Packet *p = input(port).pull();  if (p)    p = handle_packet(port, p);  return p;}#if 0Packet *SnoopTCP::PCB::add_data(Packet *p, unsigned th_seq){  bool full = next_i(_head) == _tail;  int entry = -1;    if (SEQ_GT(th_seq, _max)) {    // New packet with higher seqno - common case    if (full) {      // skip if buffer is full      DEBUG_CHATTER("buffer full");      return p;		    }    _max = th_seq;    entry = _expected_ack = _head;    _head = next_i(_head);      } else if (SEQ_LT(th_seq, _cache[_tail].seq)) {    if (SEQ_LT(th_seq, _una)) {      // already acked - don't cache      DEBUG_CHATTER("\tway out-of-order pkt %d, lastack %d\n",		    th_seq, _una);      return p;    }        // new packet earlier than anything cached    if (full) {      // skip if buffer is full      DEBUG_CHATTER("buffer full");      return p;    }    _tail = prev_i(_tail);    entry = _tail;      } else if (_tail == _head)    // nothing has been cached and we got a spurious packet    return p;    else    // somewhere in the middle    for (int i = _tail; i != _head; i = next_i(i)) {      if (_cache[i].seq == th_seq) {	// either a repeat packet or a fragment thereof	DEBUG_CHATTER("have pkt %d at %d", th_seq, i);	if (_cache[i].packet->length() <= p->length()) {	  // replace fragment/packet with new one	  _cache[i].packet->kill();	  _cache[i].packet = p->clone();	}	_cache[i].num_rxmit = 0;	_cache[i].sender_rxmit = 1;	//microtime(&(packet->snd_time));	return p;	      } else if (SEQ_GT(_cache[i].seq, th_seq)) {	// insert new packet in the middle	if (full) {	  // skip if buffer is full	  DEBUG_CHATTER("buffer full");	  return p;	}	for (int j = _tail; j != i; j = next_i(j))	  _cache[prev_i(j)] = _cache[j];	entry = i;	_tail = prev_i(_tail);	DEBUG_CHATTER("\tcache reorg; pkt %d, head %d, tail %d", 		      th_seq, _head, _tail);	break;      }    }    // Cache packet at `_cache[entry]'  //microtime(&(packet->snd_time));  assert(entry >= 0);  p->use();  _cache[entry].packet = p;  _cache[entry].seq = th_seq;  _cache[entry].num_rxmit = 0;  _cache[entry].sender_rxmit = 0;  DEBUG_CHATTER("\t%d at %d\n", th_seq, entry);    if (SEQ_LT(th_seq, _max)) {     // out-of-order     DEBUG_CHATTER("\tpkt %x out of order, last %x\n", th_seq, _max);    if (_tail == entry) {      _cache[entry].sender_rxmit = 1;      _cache[entry].num_rxmit = 0;    }    _expected_ack = _tail;  }     return p;}#endif#if 0Packet *SnoopTCP::PCB::add_ack(Packet *p, unsigned th_ack, int data_len,		       unsigned short win, SnoopTCP *snp){  DEBUG_CHATTER("ack %d, expect %d, dacks %d, seen %d dups\tcached %d-%d", 		th_ack, _expected_ack, _expected_dup_acks,		_dup_acks, _cache[_tail].seq, _cache[prev_i(_head)].seq);    if (SEQ_GT(th_ack, _una)) {    // new ack    DEBUG_CHATTER("new ack %d", th_ack);    // XXX update RTT ??    int i = _tail;    while (i != _head && SEQ_LT(_cache[i].seq, th_ack)) {      _cache[i].packet->kill();      i = next_i(i);    }    _tail = i;    _una = th_ack;    _dup_acks = 0;    _last_win = win;    return p;      } else if (SEQ_LT(th_ack, _una)) {    // out-of-order ack; just forward it on    DEBUG_CHATTER("spurious ack %d", th_ack);    return p;  } else {    if (_last_win != win || data_len > 0) {      // not a duplicate ack -- window change ad or piggyback ACK      DEBUG_CHATTER("data/window ad");      _last_win = win;      return p;    }    // duplicate ack    // first look for the appropriate cache entry    int entry = -1;    for (int i = _tail; i != _head; i = next_i(i))      if (_cache[i].seq == th_ack) {	entry = i;	break;      }    // just forward the duplicate ack if there is no such packet, or the    // sender has already retransmitted it    if (entry < 0 || _cache[entry].sender_rxmit)      return p;    // otherwise, check if we're expecting it    if (_expected_dup_acks > 0) {      --_expected_dup_acks;      DEBUG_CHATTER("expected, discarding");      // discard if not piggybacked      if (data_len)	return p;      else	return 0;    } else if (!_expected_dup_acks) {      // Compute number of expected dups      _expected_dup_acks = _head - _expected_ack;      if (_expected_dup_acks < 0)	_expected_dup_acks += SNOOP_MAX_BUF;      _expected_dup_acks--;      _expected_ack = next_i(_tail);      DEBUG_CHATTER(" ack %d expect %d more\n",		    th_ack, _expected_dup_acks);      // Retransmit      _dup_acks++;      _cache[entry].num_rxmit++;      click_chatter("dup ack %d, retransmitting", _una);      snp->output(2).push(_cache[entry].packet);      // Squelch packet if no data content      if (data_len)	return p;      else	return 0;    } else {      DEBUG_CHATTER("Help! Inconsistent state");      return p;    }  }}#endifCLICK_ENDDECLSELEMENT_REQUIRES(false)EXPORT_ELEMENT(SnoopTCP)#include <click/hashmap.cc>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -