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

📄 srqueryresponder.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * SRQueryResponder.{cc,hh} -- DSR implementation * John Bicket * * Copyright (c) 1999-2001 Massachussrqueryresponders Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "srqueryresponder.hh"#include <click/ipaddress.hh>#include <click/confparse.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/straccum.hh>#include <clicknet/ether.h>#include "srpacket.hh"CLICK_DECLSSRQueryResponder::SRQueryResponder()  :  Element(1,1),     _ip(),     _en(),     _et(0),     _link_table(0),     _arp_table(0){}SRQueryResponder::~SRQueryResponder(){}intSRQueryResponder::configure (Vector<String> &conf, ErrorHandler *errh){  int ret;  _debug = false;  ret = cp_va_parse(conf, this, errh,                    cpKeywords,		    "ETHTYPE", cpUnsigned, "Ethernet encapsulation type", &_et,                    "IP", cpIPAddress, "IP address", &_ip,		    "ETH", cpEtherAddress, "EtherAddress", &_en,		    "LT", cpElement, "LinkTable element", &_link_table,		    "ARP", cpElement, "ARPTable element", &_arp_table,		    /* below not required */		    "DEBUG", cpBool, "Debug", &_debug,                    cpEnd);  if (!_et)     return errh->error("ETHTYPE not specified");  if (!_ip)     return errh->error("IP not specified");  if (!_en)     return errh->error("ETH not specified");  if (!_link_table)     return errh->error("LT not specified");  if (!_arp_table)     return errh->error("ARPTable not specified");  if (_link_table->cast("LinkTable") == 0)     return errh->error("LinkTable element is not a LinkTable");  if (_arp_table->cast("ARPTable") == 0)     return errh->error("ARPTable element is not a ARPTable");  return ret;}intSRQueryResponder::initialize (ErrorHandler *){  return 0;}// Send a packet.// Decides whether to broadcast or unicast according to type.// Assumes the _next field already points to the next hop.voidSRQueryResponder::send(WritablePacket *p){  click_ether *eh = (click_ether *) p->data();  struct srpacket *pk = (struct srpacket *) (eh+1);  int next = pk->next();  IPAddress next_ip = pk->get_link_node(next);  EtherAddress eth_dest = _arp_table->lookup(next_ip);  sr_assert(next_ip != _ip);  eh->ether_type = htons(_et);  memcpy(eh->ether_shost, _en.data(), 6);  memcpy(eh->ether_dhost, eth_dest.data(), 6);  output(0).push(p);}boolSRQueryResponder::update_link(IPAddress from, IPAddress to, uint32_t seq, int metric) {  if (_link_table && !_link_table->update_link(from, to, seq, 0, metric)) {    click_chatter("%{element} couldn't update link %s > %d > %s\n",		  this,		  from.s().cc(),		  metric,		  to.s().cc());    return false;  }  return true;}// Continue unicasting a reply packet.voidSRQueryResponder::forward_reply(struct srpacket *pk1){  u_char type = pk1->_type;  sr_assert(type == PT_REPLY);  _link_table->dijkstra(true);  if (_debug) {    click_chatter("%{element}: forward_reply %s <- %s\n", 		  this,		  pk1->get_link_node(0).s().cc(),		  IPAddress(pk1->_qdst).s().cc());  }  if(pk1->next() >= pk1->num_links()) {    click_chatter("%{element} forward_reply strange next=%d, nhops=%d", 		  this,		  pk1->next(), 		  pk1->num_links());    return;  }  Path fwd;  Path rev;  for (int i = 0; i < pk1->num_links(); i++) {    fwd.push_back(pk1->get_link_node(i));  }  rev = reverse_path(fwd);  struct timeval now;  click_gettimeofday(&now);  int len = pk1->hlen_wo_data();  WritablePacket *p = Packet::make(len + sizeof(click_ether));  if(p == 0)    return;  click_ether *eh = (click_ether *) p->data();  struct srpacket *pk = (struct srpacket *) (eh+1);  memcpy(pk, pk1, len);  pk->set_next(pk1->next() - 1);  send(p);}void SRQueryResponder::start_reply(IPAddress src, IPAddress qdst, uint32_t seq){  _link_table->dijkstra(false);  Path best = _link_table->best_route(src, false);  bool best_valid = _link_table->valid_route(best);    int si = 0;    for(si = 0; si < _seen.size(); si++){    if(src == _seen[si]._src && seq == _seen[si]._seq) {      break;    }  }  if (si == _seen.size()) {    if (_seen.size() >= 100) {      _seen.pop_front();    }    _seen.push_back(Seen(src, qdst, seq));    si = _seen.size() - 1;  }  if (best == _seen[si].last_path_response) {    /*     * only send replies if the "best" path is different     * from the last reply     */    return;  }  _seen[si]._src = src;  _seen[si]._dst = qdst;  _seen[si]._seq = seq;  _seen[si].last_path_response = best;    if (!best_valid) {    click_chatter("%{element} :: %s :: invalid route for src %s: %s\n",		  this,		  __func__,		  src.s().cc(),		  path_to_string(best).cc());    return;  }  int links = best.size() - 1;  int len = srpacket::len_wo_data(links);  if (_debug) {    click_chatter("%{element}: start_reply %s <- %s\n",		  this,		  src.s().cc(),		  qdst.s().cc());  }  WritablePacket *p = Packet::make(len + sizeof(click_ether));  if(p == 0)    return;  click_ether *eh = (click_ether *) p->data();  struct srpacket *pk_out = (struct srpacket *) (eh+1);  memset(pk_out, '\0', len);  pk_out->_version = _sr_version;  pk_out->_type = PT_REPLY;  pk_out->_flags = 0;  pk_out->set_seq(seq);  pk_out->set_num_links(links);  pk_out->set_next(links-1);  pk_out->_qdst = qdst;    for (int i = 0; i < links; i++) {    pk_out->set_link(i,		     best[i], best[i+1],		     _link_table->get_link_metric(best[i], best[i+1]),		     _link_table->get_link_metric(best[i+1], best[i]),		     _link_table->get_link_seq(best[i], best[i+1]),		     _link_table->get_link_age(best[i], best[i+1]));  }    send(p);}// Got a reply packet whose ultimate consumer is us.// Make a routing table entry if appropriate.voidSRQueryResponder::got_reply(struct srpacket *pk){  IPAddress dst = IPAddress(pk->_qdst);  sr_assert(dst);  if (_debug) {    click_chatter("%{element}: got_reply %s <- %s\n", 		  this,		  _ip.s().cc(),		  dst.s().cc());  }  _link_table->dijkstra(true);}voidSRQueryResponder::push(int, Packet *p_in){  click_ether *eh = (click_ether *) p_in->data();  struct srpacket *pk = (struct srpacket *) (eh+1);  if (EtherAddress(eh->ether_shost) == _en) {    click_chatter("%{element}: packet from me",		  this);    p_in->kill();    return;  }    u_char type = pk->_type;  IPAddress dst = IPAddress(pk->_qdst);    if (type != PT_REPLY) {    if (dst == _ip) {      start_reply(pk->get_link_node(0), pk->_qdst, pk->seq());    }    p_in->kill();    return;  }  if (eh->ether_type != htons(_et)) {    click_chatter("%{element}: bad ether_type %04x",		  this,		  ntohs(eh->ether_type));    p_in->kill();    return;  }  if(pk->get_link_node(pk->next()) != _ip){    // it's not for me. these are supposed to be unicast,    // so how did this get to me?    click_chatter("%{element}: reply not for me %d/%d %s",		  this,		  pk->next(),		  pk->num_links(),		  pk->get_link_node(pk->next()).s().cc());    p_in->kill();    return;  }      /* update the metrics from the packet */  for(int i = 0; i < pk->num_links(); i++) {    IPAddress a = pk->get_link_node(i);    IPAddress b = pk->get_link_node(i+1);    int fwd_m = pk->get_link_fwd(i);    int rev_m = pk->get_link_fwd(i);    uint32_t seq = pk->get_link_seq(i);    /* don't update my immediate neighbor. see below */    if (fwd_m && !update_link(a,b,seq,fwd_m)) {      click_chatter("%{element} couldn't update fwd_m %s > %d > %s\n",		    this,		    a.s().cc(),		    fwd_m,		    b.s().cc());    }    if (rev_m && !update_link(b,a,seq,rev_m)) {      click_chatter("%{element} couldn't update rev_m %s > %d > %s\n",		    this,		    b.s().cc(),		    rev_m,		    a.s().cc());    }  }      IPAddress neighbor = pk->get_link_node(pk->num_links());  sr_assert(neighbor);    if(pk->next() == 0){    // I'm the ultimate consumer of this reply. Add to routing tbl.    got_reply(pk);  } else {    // Forward the reply.    forward_reply(pk);  }  p_in->kill();  return;    }enum {H_DEBUG, H_IP};static String SRQueryResponder_read_param(Element *e, void *thunk){  SRQueryResponder *td = (SRQueryResponder *)e;  switch ((uintptr_t) thunk) {  case H_DEBUG:    return String(td->_debug) + "\n";  case H_IP:    return td->_ip.s() + "\n";  default:    return String();  }}static int SRQueryResponder_write_param(const String &in_s, Element *e, void *vparam,		      ErrorHandler *errh){  SRQueryResponder *f = (SRQueryResponder *)e;  String s = cp_uncomment(in_s);  switch((int)vparam) {  case H_DEBUG: {    //debug    bool debug;    if (!cp_bool(s, &debug))       return errh->error("debug parameter must be boolean");    f->_debug = debug;    break;  }  }  return 0;}voidSRQueryResponder::add_handlers(){  add_read_handler("debug", SRQueryResponder_read_param, (void *) H_DEBUG);  add_read_handler("ip", SRQueryResponder_read_param, (void *) H_IP);  add_write_handler("debug", SRQueryResponder_write_param, (void *) H_DEBUG);}// generate Vector template instance#include <click/vector.cc>#include <click/hashmap.cc>#include <click/dequeue.cc>#if EXPLICIT_TEMPLATE_INSTANCEStemplate class Vector<SRQueryResponder::IPAddress>;template class DEQueue<SRQueryResponder::Seen>;#endifCLICK_ENDDECLSEXPORT_ELEMENT(SRQueryResponder)

⌨️ 快捷键说明

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