📄 lookuplocalgridroute.cc
字号:
/* * lookuplocalgridroute.{cc,hh} -- Grid multihop local routing element * Douglas S. J. De Couto * * Copyright (c) 2000 Massachusetts 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 <click/confparse.hh>#include <click/error.hh>#include <clicknet/ether.h>#include <clicknet/ip.h>#include <click/standard/scheduleinfo.hh>#include <click/router.hh>#include <click/glue.hh>#include <elements/grid/grid.hh>#include <elements/grid/gridgatewayinfo.hh>#include <elements/grid/lookuplocalgridroute.hh>#include <elements/grid/linktracker.hh>#include <elements/grid/gridgenericrt.hh>#include <elements/grid/gridgenericlogger.hh>CLICK_DECLSint GridRouteActor::_next_free_cb = 0;#define NOISY 0LookupLocalGridRoute::LookupLocalGridRoute() : Element(2, 4), _gw_info(0), _link_tracker(0), _rtes(0), _any_gateway_ip(0), _task(this), _log(0){}LookupLocalGridRoute::~LookupLocalGridRoute(){}void *LookupLocalGridRoute::cast(const char *n){ if (strcmp(n, "LookupLocalGridRoute") == 0) return (LookupLocalGridRoute *)this; else return 0;}intLookupLocalGridRoute::configure(Vector<String> &conf, ErrorHandler *errh){ int res = cp_va_parse(conf, this, errh, cpEthernetAddress, "source Ethernet address", &_ethaddr, cpIPAddress, "source IP address", &_ipaddr, cpOptional, cpElement, "GenericGridRouteTable element", &_rtes, cpKeywords, "GWI", cpElement, "GridGatewayInfo element", &_gw_info, "LT", cpElement, "LinkTracker element", &_link_tracker, "LOG", cpElement, "GridGenericLogger element", &_log, cpEnd); _any_gateway_ip = htonl((ntohl(_ipaddr.addr()) & 0xFFffFF00) | 254); return res;}intLookupLocalGridRoute::initialize(ErrorHandler *errh){ if (_rtes && _rtes->cast("GridGenericRouteTable") == 0) { return errh->error("%s: GridRouteTable argument %s has the wrong type", id().cc(), _rtes->id().cc()); } #if 0 else if (_rtes == 0) { return errh->error("%s: no GridRouteTable element given", id().cc()); }#endif if (_gw_info && _gw_info->cast("GridGatewayInfo") == 0) { return errh->error("%s: GridGatewayInfo argument %s has the wrong type", id().cc(), _gw_info->id().cc()); } if (_link_tracker && _link_tracker->cast("LinkTracker") == 0) { return errh->error("%s: LinkTracker argument %s has the wrong type", id().cc(), _link_tracker->id().cc()); } if (_log && _log->cast("GridGenericLogger") == 0) { return errh->error("%s: GridGenericLogger element %s has the wrong type", id().cc(), _log->id().cc()); } if (input_is_pull(0)) ScheduleInfo::join_scheduler(this, &_task, errh); return 0;}boolLookupLocalGridRoute::run_task(){ Packet *p = input(0).pull(); if (p) push(0, p); _task.fast_reschedule(); return p != 0;}boolLookupLocalGridRoute::is_gw(){ return _gw_info && _gw_info->is_gateway(); }typedef GridRouteActionCallback GRCB;voidLookupLocalGridRoute::push(int port, Packet *packet){ /* * input 1 and output 1 hook up to higher level (e.g. ip), input 0 * and output 0 hook up to lower level (e.g. ethernet) */ assert(packet); if (port == 0) { /* * input from net device */ grid_hdr *gh = (grid_hdr *) (packet->data() + sizeof(click_ether)); switch (gh->type) { case grid_hdr::GRID_NBR_ENCAP: case grid_hdr::GRID_LOC_REPLY: case grid_hdr::GRID_ROUTE_PROBE: case grid_hdr::GRID_ROUTE_REPLY: { /* * try to either receive the packet or forward it */ struct grid_nbr_encap *encap = (grid_nbr_encap *) (packet->data() + sizeof(click_ether) + gh->hdr_len); IPAddress dest_ip(encap->dst_ip);#if NOISY click_chatter("lr %s: got %s packet for %s; I am %s; agi=%s, is_gw = %d\n", id().cc(), grid_hdr::type_string(gh->type).cc(), dest_ip.s().cc(), _ipaddr.s().cc(), _any_gateway_ip.s().cc(), is_gw() ? 1 : 0);#endif // is the packet for us? if ((dest_ip == _ipaddr) || (dest_ip == _any_gateway_ip && is_gw())) { // is it IP data? If so, send it to IP input path. if (gh->type == grid_hdr::GRID_NBR_ENCAP) {#if NOISY click_chatter("%s: got an IP packet for us %s", id().cc(), dest_ip.s().cc());#endif packet->pull(sizeof(click_ether) + gh->hdr_len + sizeof(grid_nbr_encap)); notify_route_cbs(packet, dest_ip, GRCB::SendToIP, 0, 0); output(1).push(packet); } else click_chatter("%s: got %s packet for us, but don't know how to handle it", id().cc(), grid_hdr::type_string(gh->type).cc()); } else { // packet is not for us, try to forward it! forward_grid_packet(packet, encap->dst_ip); } } break; default: click_chatter("%s: received unexpected Grid packet type: %s", id().cc(), grid_hdr::type_string(gh->type).cc()); notify_route_cbs(packet, 0, GRCB::Drop, GRCB::UnknownType, 0); output(3).push(packet); } } else { /* * input from higher level protocol -- expects IP packets * annotated with dst IP address. */ assert(port == 1); // check to see is the desired dest is our neighbor IPAddress dst = packet->dst_ip_anno();#if NOISY click_chatter("lr %s: got packet for %s; I am %s; agi=%s, is_gw=%d\n", id().cc(), dst.s().cc(), _ipaddr.s().cc(), _any_gateway_ip.s().cc(), is_gw() ? 1 : 0);#endif if (dst == _any_gateway_ip && is_gw()) { packet->kill(); } else if (dst == _ipaddr) { click_chatter("%s: got IP packet from us for our address; looping it back. Check the configuration.", id().cc()); output(1).push(packet); } else { // encapsulate packet with grid hdr and try to send it out WritablePacket *new_packet = packet->push(sizeof(click_ether) + sizeof(grid_hdr) + sizeof(grid_nbr_encap)); memset(new_packet->data(), 0, sizeof(click_ether) + sizeof(grid_hdr) + sizeof(grid_nbr_encap)); struct click_ether *eh = (click_ether *) new_packet->data(); eh->ether_type = htons(ETHERTYPE_GRID); struct grid_hdr *gh = (grid_hdr *) (new_packet->data() + sizeof(click_ether)); gh->hdr_len = sizeof(grid_hdr); gh->total_len = new_packet->length() - sizeof(click_ether); // encapsulate everything we get, don't look inside it for length info gh->total_len = htons(gh->total_len); gh->type = grid_hdr::GRID_NBR_ENCAP; /* FixSrcLoc will see that the gh->ip and gh->tx_ip fields are the same, and will fill in gh->loc, etc. */ // gh->tx_ip is set in forward_grid_packet() gh->ip = _ipaddr; struct grid_nbr_encap *encap = (grid_nbr_encap *) (new_packet->data() + sizeof(click_ether) + sizeof(grid_hdr)); encap->hops_travelled = 0; encap->dst_ip = dst;#ifndef SMALL_GRID_HEADERS encap->dst_loc_good = false;#endif forward_grid_packet(new_packet, dst); } }}voidLookupLocalGridRoute::add_handlers(){ add_default_handlers(true);}boolLookupLocalGridRoute::get_next_hop(IPAddress dest_ip, EtherAddress *dest_eth, IPAddress *next_hop_ip, unsigned char *next_hop_interface) const{ assert(dest_eth != 0); GridGenericRouteTable::RouteEntry rte; bool found_route; if (dest_ip == _any_gateway_ip) { found_route = _rtes->current_gateway(rte); // what if we are being asked to forward a grid packet to an // internet host, but we have no local routes to a gateway? // drop here? // i guess we could do a loc query for a gateway... seems a little // sketchy to me though. } else { found_route = _rtes->get_one_entry(dest_ip, rte); } /* did we have a route? */ if (found_route && rte.good()) { *dest_eth = rte.next_hop_eth; *next_hop_ip = rte.next_hop_ip; *next_hop_interface = rte.next_hop_interface; return true; } return false;}voidLookupLocalGridRoute::forward_grid_packet(Packet *xp, IPAddress dest_ip){ WritablePacket *packet = xp->uniqueify(); /* * packet must have a MAC hdr, grid_hdr, and a grid_nbr_encap hdr on * it. This function will update the hop count, transmitter ip and * loc (us) and dst/src MAC addresses. Sender ip and loc info will * not be touched, so if we are originating the packet, those have * to be setup before calling this function. Similarly, the * destination ip and loc info must be set by whoever (or whatever * element) originates the packet. The originator should probably * set the nb->dst_loc_good to false, so that if we don't find a * local route the loc querier will know to lookup the destination * location before using geographic forwarding. */ if (_rtes == 0) { // no GridRouteTable next-hop table in configuration click_chatter("%s: can't forward packet for %s; there is no routing table, trying geographic forwarding", id().cc(), dest_ip.s().cc()); notify_route_cbs(packet, dest_ip, GRCB::FallbackToGF, 0, 0); output(2).push(packet); return; } struct grid_nbr_encap *encap = (grid_nbr_encap *) (packet->data() + sizeof(click_ether) + sizeof(grid_hdr)); EtherAddress next_hop_eth; IPAddress next_hop_ip; unsigned char next_hop_interface = 0; bool found_next_hop = get_next_hop(dest_ip, &next_hop_eth, &next_hop_ip, &next_hop_interface); if (found_next_hop) { struct click_ether *eh = (click_ether *) packet->data(); memcpy(eh->ether_shost, _ethaddr.data(), 6); memcpy(eh->ether_dhost, next_hop_eth.data(), 6); struct grid_hdr *gh = (grid_hdr *) (packet->data() + sizeof(click_ether)); gh->tx_ip = _ipaddr; encap->hops_travelled++; // leave src location update to FixSrcLoc element int sig = 0; int qual = 0; struct timeval tv = { 0, 0 };#ifdef CLICK_USERLEVEL if (_link_tracker) _link_tracker->get_stat(next_hop_ip, sig, qual, tv);#endif unsigned int data2 = (qual << 16) | ((-sig) & 0xFFff); notify_route_cbs(packet, dest_ip, GRCB::ForwardDSDV, next_hop_ip, data2); SET_PAINT_ANNO(packet, next_hop_interface); output(0).push(packet); } else {#if NOISY click_chatter("%s: unable to forward packet for %s with local routing, trying geographic routing", id().cc(), dest_ip.s().cc());#endif // logging notify_route_cbs(packet, dest_ip, GRCB::FallbackToGF, 0, 0); if (_log) _log->log_no_route(packet, Timestamp::now()); output(2).push(packet); }}CLICK_ENDDECLSEXPORT_ELEMENT(LookupLocalGridRoute)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -