📄 sense.h
字号:
/************************************************************************ * @<title> SENSE Library </title>@ * * @<h1> sense.h </h1>@ * This header file provides * necessary functionalities for network simulation. All SENSE * components must include this header file. * * @<!--Copyright 2003 Gilbert (Gang) Chen, Boleslaw K. Szymanski and * Rensselaer Polytechnic Institute. All worldwide rights reserved. A * license to use, copy, modify and distribute this software for * non-commercial research purposes only is hereby granted, provided * that this copyright notice and accompanying disclaimer is not * modified or removed from the software. * * DISCLAIMER: The software is distributed "AS IS" without any express * or implied warranty, including but not limited to, any implied * warranties of merchantability or fitness for a particular purpose * or any warranty of non-infringement of any current or pending * patent rights. The authors of the software make no representations * about the suitability of this software for any particular * purpose. The entire risk as to the quality and performance of the * software is with the user. Should the software prove defective, the * user assumes the cost of all necessary servicing, repair or * correction. In particular, neither Rensselaer Polytechnic * Institute, nor the authors of the software are liable for any * indirect, special, consequential, or incidental damages related to * the software, to the maximum extent the law permits. -->@ * ************************************************************************/#ifndef SENSE_H#define SENSE_H#include "config.h"const double speed_of_light=299792458.0;#include <string>using std::string;/************************************************************************ * SENSE is built on top of COST, and makes use of @CorsaAllocator@ defined * in corsa_alloc.h. ************************************************************************/#include "cost.h"#include "corsa_alloc.h"/************************************************************************ * @<h2> Packet Management in SENSE </h2>@ * * There are two main design goals on the packet management in SENSE: to * allow components to pass packets in two forms, either as a packet * structure or as a pointer to a packet structure, and to share a * packet among all receiving components if the packet is passed by a * pointer. * * The first goal is achieved by using a modern C++ technique, * referred to as traits. According to Bjarne Stroustrup, a trait is * "a small object whose main purpose is to carry information used by * another object or algorithm to determine policy or implementation * details." In SENSE, a special trait class is declared which can be * used to tell if a certain template parameter is a packet structure * or a packet pointer. * The second goal of sharing a packet through the pointer is done by * the use of a popular programming technique, reference counting. * When a component is about to own a packet, it must increase the reference * count of the packet to indicate the newly created ownership. When a component * is about to release a packet, it needs to decrease the reference * count. Only when the reference count goes to zero will the packet be * actually deleted. * * @<h2>ether_addr_t</h2>@ * * This class defines the addresses used in Ethernet. It is in fact a * wrapper class over @int@. The @compare@ struct is an function * object that can be used by STL containers. ************************************************************************/class ether_addr_t{ public: enum { LENGTH = 6, BROADCAST = -1 }; ether_addr_t () : addr (0) {} ; ether_addr_t (int a) : addr (a) {}; bool operator == (const ether_addr_t& another) const { return addr==another.addr; } bool operator == (const int& another) const { return addr==another; } bool operator < (const ether_addr_t& another) const { return addr<another.addr; } bool operator > (const ether_addr_t& another) const { return addr>another.addr; } operator const int& () const { return addr; }; struct compare { bool operator() ( const ether_addr_t & e1, const ether_addr_t & e2) { return e1.addr > e2.addr; } }; private: int addr;};/************************************************************************ * This is the packet trait class that takes one template parameter, * @T@. It serves dual purposes. First, if @T@ is a pointer, then * @nonpointer_t@ gives the corresponding structure. Second, it * defines three member functions, which are to be called when * respective operations need to be performed. * * In the general declaration, @nonpointer_t@ is just @T@, and in all * three member function no action is taken. This is for packets passed * as plain structures. ************************************************************************/template <class T>class packet_trait{ public: typedef T nonpointer_t; static void free(const T&) { } static void free(T&t) { t.~T(); } static void init(T&t) { new (&t) T; } static void init(const T&) { } static void inc_ref(const T&) { } static void dump(std::string& str, const T&p) { p.dump(str) ;} static void check_ref(const T&, int) { }};/************************************************************************ * A smart packet is designed for layered network architecture. It has * two important fields, @hdr@ for the header and @pld@ for the * payload (which is usually the encapsulated higher layer * packet). There are two ways to access the header or payload, * working for two different cases. * * Let us use a simple example to illustrate the usage of this class * in two cases. Suppose we have a declaration @P@ @p@ (most likely * this is an argument). If we know for sure that @p@ is a pointer, * then we can simply use @p->hdr@ to access the header, @p->pld@ to * access the payload. * * However, if we don't know whether @p@ is a pointer or a structure * (which happens when @P@ is a template parameter), we cannot access * the field directly, and we have to use the function @access_hdr@ or * @access_pld@. We cannot do @P::access_hdr(p)@, because @P@ may be * a pointer. However, we can always rely on @packet_trait@ to strip * of the pointer, so we have * @packet_trait<P>::nonpointer_t::access_hdr(p)@. This expression * looks ugly, but if we can define beforehand the nonpointer type as, say, * @P_T@, by doing '@typedef@ @packet_trait<P>::nonpointer_t@ @P_T@;', * then the original expression can be simplified as * @P_T::access_hdr(p)@. Not too bad, right? * ************************************************************************/template <class H, class P>class smart_packet_t{ public: inline static smart_packet_t<H,P> * alloc(); inline void free(); inline void destroy(); inline void inc_ref(); inline smart_packet_t<H,P> * copy(); inline void inc_pld_ref() const; inline bool check_ref(int r) { return r<=refcount; } static P& access_pld(smart_packet_t<H,P>* p) { return p->pld; } static P& access_pld(smart_packet_t<H,P>& p) { return p.pld; } static H& access_hdr(smart_packet_t<H,P>* p) { return p->hdr; } static H& access_hdr(smart_packet_t<H,P>& p) { return p.hdr; } H* operator ->() { return &hdr; } std::string dump() const; H hdr; P pld; private: static CorsaAllocator m_allocator; int refcount;};/************************************************************************ * We use our own memory allocator, @CorsaAllocator@, which is more * efficient than the default memory allocator, since for each packet * type we only need to deal with memory blocks of the same size. ************************************************************************/template <class H, class P> CorsaAllocator smart_packet_t<H,P>::m_allocator (sizeof(smart_packet_t<H,P>));/************************************************************************ * This function creates a new packet obtained from the allocator. It then * sets @p->pld@ to null if @p->pld@ is a pointer, and the reference count to 1. ************************************************************************/template <class H, class P>smart_packet_t<H,P>* smart_packet_t<H,P>::alloc(){ smart_packet_t<H,P>* p=static_cast<smart_packet_t<H,P>*>(m_allocator.alloc()); packet_trait<H>::init(p->hdr); packet_trait<P>::init(p->pld); p->refcount=1; return p;}/************************************************************************ * This function creates a new copy from an existing packet. ************************************************************************/template <class H, class P>smart_packet_t<H,P>* smart_packet_t<H,P>::copy(){ smart_packet_t<H,P>* p=static_cast<smart_packet_t<H,P>*>(m_allocator.alloc()); packet_trait<H>::init(p->hdr); packet_trait<P>::init(p->pld); p->hdr=hdr; p->pld=pld; inc_pld_ref(); p->refcount=1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -