📄 todevice.cc
字号:
/* * todevice.{cc,hh} -- element sends packets to BSD devices. * Robert Morris * Eddie Kohler: register once per configuration * Nickolai Zeldovich, Luigi Rizzo: BSD * * Copyright (c) 1999-2001 Massachusetts Institute of Technology * Copyright (c) 2000 Mazu Networks, Inc. * Copyright (c) 2001 International Computer Science Institute * * 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/glue.hh>#include "todevice.hh"#include <click/error.hh>#include <click/etheraddress.hh>#include <click/confparse.hh>#include <click/router.hh>#include <click/standard/scheduleinfo.hh>/* for watching when devices go offline */static AnyDeviceMap to_device_map;static int to_device_count;#if 0 /* Not yet in BSD XXX */static struct notifier_block device_notifier;extern "C" {static int device_notifier_hook(struct notifier_block *nb, unsigned long val, void *v);}#endifstatic voidtodev_static_initialize(){ if (++to_device_count == 1) { to_device_map.initialize();#if 0 /* XXX not yet in BSD XXX */ device_notifier.notifier_call = device_notifier_hook; device_notifier.priority = 1; device_notifier.next = 0; register_netdevice_notifier(&device_notifier);#endif }}static voidtodev_static_cleanup(){ if (--to_device_count <= 0) {#if 0 /* XXX not yet in BSD */ unregister_netdevice_notifier(&device_notifier);#endif }}ToDevice::ToDevice(){ add_input(); todev_static_initialize();}ToDevice::~ToDevice(){ todev_static_cleanup();}intToDevice::configure(Vector<String> &conf, ErrorHandler *errh){ _burst = 16; bool allow_nonexistent = false; if (cp_va_parse(conf, this, errh, cpString, "device name", &_devname, cpOptional, cpUnsigned, "burst size", &_burst, cpKeywords, "BURST", cpUnsigned, "burst size", &_burst, "ALLOW_NONEXISTENT", cpBool, "allow nonexistent interface?", &allow_nonexistent, cpEnd) < 0) return -1; if (find_device(allow_nonexistent, &to_device_map, errh) < 0) return -1; return 0;}intToDevice::initialize(ErrorHandler *errh){ to_device_map.insert(this); ScheduleInfo::initialize_task(this, &_task, device() != 0, errh); _signal = Notifier::upstream_empty_signal(this, 0, &_task);#ifdef HAVE_STRIDE_SCHED // start out with max number of tickets set_max_tickets( _task.tickets() ); _task.set_tickets(Task::DEFAULT_TICKETS);#endif reset_counts(); return 0;}voidToDevice::reset_counts(){ _npackets = 0; _busy_returns = 0; }voidToDevice::cleanup(CleanupStage){ to_device_map.remove(this);}boolToDevice::run_task(){ int busy; int sent = 0; // click_chatter("ToDevice::run_task()."); while (sent < _burst && (busy = IF_QFULL(&device()->if_snd)) == 0) { Packet *p = input(0).pull(); if (!p) break; _npackets++; struct mbuf *m = p->steal_m(); if (ether_output_frame(device(), m) != 0) break; sent++; } if (busy) _busy_returns++;#if 0 adjust_tickets(sent);#endif if (sent > 0 || busy || _signal) _task.fast_reschedule(); return sent > 0;}static StringToDevice_read_calls(Element *f, void *){ ToDevice *td = (ToDevice *)f; return String(td->_busy_returns) + " device busy returns\n" + String(td->_npackets) + " packets sent\n" + String();}static StringToDevice_read_stats(Element *e, void *thunk){ ToDevice *td = (ToDevice *)e; int which = reinterpret_cast<int>(thunk); switch (which) { case 0: return String(td->_npackets) + "\n"; default: return String(); }}static intToDevice_write_stats(const String &, Element *e, void *, ErrorHandler *){ ToDevice *td = (ToDevice *)e; td->reset_counts(); return 0;}voidToDevice::add_handlers(){ add_read_handler("calls", ToDevice_read_calls, 0); add_read_handler("packets", ToDevice_read_stats, 0); add_write_handler("reset_counts", ToDevice_write_stats, 0); add_task_handlers(&_task);}ELEMENT_REQUIRES(AnyDevice bsdmodule)EXPORT_ELEMENT(ToDevice)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -