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

📄 xorpdev_101.tex

📁 xorp源码hg
💻 TEX
📖 第 1 页 / 共 4 页
字号:
Listing we can see that this is defined as:\\{\stt typedef XorpCallback1<void, const XrlError\&>::RefPtr  AddRoute4CB;}\\This defines {\stt AddRoute4CB} to be a {\it callback} which returns type{\stt void} with one parameter of type {\stt const XrlError\&}.But what exactly is a {\stt callback}?Well, what we want is to call the {\stt send\_add\_route4()} method tosend an XRL request to the \SRI process, and then to go off and doother things while we're waiting for the response to come back.  In amulti-threaded architecture, this might be achieved by having {\sttsend\_add\_route4()} block until the response is ready, but XORP isdeliberately {\it not} a multi-threaded architecture. Thus whathappens is that {\stt send\_add\_route4()} will return immediately.It will return false if a local error occurs, but will normally returntrue before the XRL has actually been sent.  Some time later theresponse will come back from the \SRI process, and we need a way todirect the response to the right class instance that is expecting it.This is achieved in XORP through the use of {\it callbacks}.A callback is created using the {\stt callback()} function fromlibxorp.  We'll discuss this in more detail when we look at how the\SRI process sends changes to the RIB in Section \ref{rib}.  For now,it suffices to say that a callback must be created and passed into{\stt send\_add\_route4()}, and that this is how the response from the{\stt add\_route4()} XRL is returned to the right place.\newpage%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\subsection{Generating stub code for the target}The other side to the XRL story is how the XRL target implements theXRLs.  To illustrate this, we will look at how the \SRI processimplements the XRL interface defined in {\stt static\_routes.xif}.A XORP process can implement more than one interface.  In fact mostXORP processes implement a special-purpose interface and also the{\stt common} interface, which provides XRLs to query basic versionand status information about a target process.\vspace{0.1in}To see what interfaces a particular target process supports we mustlook in the {\stt xorp/xrl/targets} directory.  Listing\ref{lst:sr.tgt} shows the entire contents of {\sttstatic\_routes.tgt}.This file defines that the XRL target called \SR implements the twointerfaces {\stt common/0.1} and {\stt static\_routes/0.1}.In the \SRI process, we'd prefer not to have to write all the code tounmarshall XRLs into C++, and marshall the response back into an XRLresponse, so again we use machine-generated C++ stubs to free theprogrammer from having to do most of the tedious work.  Listing\ref{lst:tgt.makefile} shows a number of fragments from {\sttxorp/xrl/targets/Makefile.am} related to the {\stt static\_routes}target.In Listing \ref{lst:tgt.makefile}, the first important point is that{\stt static\_routes.tgt} is added to the list of {\stt tgt\_files}.From each {\stt .tgt} file, a {\stt .xrls} file will be generatedusing the python script {\stt tgt-gen} according to the magic at thebottom of the listing.In the case of {\stt static\_routes.tgt}, the file {\sttstatic\_routes.xrls} will be generated.  This file simply contains alisting of all the fully expanded XRLs supported by the \SR XRLtarget.The next important point to note from Listing \ref{lst:tgt.makefile}is that we have specified that we want to build a library called {\sttlibstaticroutesbase.la}.  This is going to be the library that the \SRIprocess links with to get access to all the stub code to implementthe target part of this interface.Finally there's the directive to build {\stt libstaticroutesbase.la}from the machine-generated source files {\stt static\_routes\_base.hh}and {\stt static\_routes\_base.cc}, and that these files depend on thefiles {\stt common.xif} and {\stt static\_routes.xif}.\vspace{0.1in}So, what does {\stt libstaticroutesbase.la} actually provide?  Listing\ref{lst:sr.base} shows some extracts from {\sttstatic\_routes\_base.hh}.Basically {\stt libstaticroutesbase.la} defines a class called \\{\sttXrlStaticRoutesTargetBase} which will be used to receive XRL requests.The constructor for {\stt XrlStaticRoutesTargetBase} takes a singleparameter which is typically the {\stt XrlRouter} for the process.  An{\stt XrlRouter} is an object that is bound to an {\it EventLoop} andwhich sends and receives XRL requests.  Each process has its own {\itEventLoop}.  In Section \ref{main} we'll look at what the EventLoopdoes.  In any event, once an instance of {\sttXrlStaticRoutesTargetBase} has been created with a pointer to aworking {\stt XrlRouter}, then the process is ready to receive XRLrequests for the \SR interface.  But first we have to actually writesome code.If we look in at Listing \ref{lst:sr.base}, we see that the method{\stt static\_routes\_0\_1\_add\_route4()} has been defined.  However themethod is a {\it pure virtual}, which means that it is defined here,but there is no implementation of this in {\sttXrlStaticRoutesTargetBase}.  So how do we actually make use of this?The general idea is that the stub generation code knows the syntax forthis target interface, so it generates all the code needed to checkthat incoming requests match the defined syntax and handle errors ifthey don't.  But the stub generation code has no idea what thisinterface actually {\it does}.  We need to supply an implemenation for {\sttstatic\_routes\_0\_1\_add\_route4()} that actually does what we want whenthis XRL is called.\newpage\begin{lstlisting}[caption={Contents of {\stt	xorp/xrl/targets/static\_routes.tgt} %                                     \label{lst:sr.tgt} } ]{}#include "common.xif"#include "finder_event_observer.xif"#include "policy_backend.xif"#include "static_routes.xif"target static_routes implements	common/0.1,				\				finder_event_observer/0.1,		\				policy_backend/0.1,			\				static_routes/0.1\end{lstlisting}\begin{lstlisting}[caption={Extracts from {\stt xorp/xrl/targets/Makefile.am} %                                     \label{lst:tgt.makefile} } ]{}################################################################################ Xrl Target related################################################################################ Add your target file heretgt_files                = bgp.tgt...tgt_files               += static_routes.tgt...# Automatically compute the list of the *.xrls filesxrls_files               = $(tgt_files:%.tgt=%.xrls)...# Add your target's library herenoinst_LTLIBRARIES	 = libbgpbase.lanoinst_LIBRARIES         = libbgpbase.a...noinst_LTLIBRARIES	+= libstaticroutesbase.la...# StaticRouteslibstaticroutesbase_la_SOURCES = static_routes_base.hh static_routes_base.cc$(srcdir)/static_routes_base.hh $(srcdir)/static_routes_base.cc:	\		$(INTERFACES_DIR)/common.xif 				\		$(INTERFACES_DIR)/finder_event_observer.xif		\		$(INTERFACES_DIR)/policy_backend.xif			\		$(INTERFACES_DIR)/static_routes.xif...################################################################################ Implicit Rules and related###############################################################################SCRIPT_DIR=$(top_srcdir)/xrl/scriptsTGTGEN_PY=$(SCRIPT_DIR)/tgt-gen# If this code is commented out, please upgrade to python2.0 or above.@PYTHON_BUILD@$(srcdir)/%_base.hh $(srcdir)/%_base.cc %_base.hh %_base.cc   \@PYTHON_BUILD@$(srcdir)/%.xrls: $(srcdir)/%.tgt $(TGTGEN_PY)@PYTHON_BUILD@      $(PYTHON) $(TGTGEN_PY) -I$(INTERFACES_DIR) $<\end{lstlisting}\newpage\begin{lstlisting}[caption={Extracts from {\stt xorp/xrl/targets/static\_routes\_base.hh}%                                     \label{lst:sr.base} } ]{}class XrlStaticRoutesTargetBase {...public:    /**     * Constructor.     *     * @param cmds an XrlCmdMap that the commands associated with the target     *             should be added to.  This is typically the XrlRouter     *             associated with the target.     */    XrlStaticRoutesTargetBase(XrlCmdMap* cmds = 0);...protected:    /**     *  Pure-virtual function that needs to be implemented to:     *     *  Add/replace/delete a static route.     *     *  @param unicast if true, then the route would be used for unicast     *  routing.     *     *  @param multicast if true, then the route would be used in the MRIB     *  (Multicast Routing Information Base) for multicast purpose (e.g.,     *  computing the Reverse-Path Forwarding information).     *     *  @param network the network address prefix this route applies to.     *     *  @param nexthop the address of the next-hop router for this route.     *     *  @param metric the metric distance for this route.     */    virtual XrlCmdError static_routes_0_1_add_route4(        // Input values,        const bool&     unicast,        const bool&     multicast,        const IPv4Net&  network,        const IPv4&     nexthop,        const uint32_t& metric) = 0;...}\end{lstlisting}\newpage\begin{lstlisting}[caption={Extracts from {\stt xorp/static\_routes/xrl\_static\_routes\_node.hh} %                                     \label{lst:srn.hh} } ]{}class XrlStaticRoutesNode : public StaticRoutesNode,			    public XrlStdRouter,			    public XrlStaticRoutesTargetBase {public:    XrlStaticRoutesNode(EventLoop&	eventloop,			const string&	class_name,			const string&	finder_hostname,			uint16_t	finder_port,			const string&	finder_target,			const string&	fea_target,			const string&	rib_target);...protected:    //    // XRL target methods    //...    XrlCmdError static_routes_0_1_add_route4(        // Input values,        const bool&     unicast,        const bool&     multicast,        const IPv4Net&  network,        const IPv4&     nexthop,        const uint32_t& metric);...private:...    XrlRibV0p1Client    _xrl_rib_client;...}\end{lstlisting}So now we come at last to the implementation of the \SRI process.This is in the \\{\stt xorp/static\_routes} directory.  We have created a file called {\stt xrl\_static\_routes\_node.hh} todefine our class that actually implements the code to receive andprocess XRLs.  An extract from this is shown in Listing\ref{lst:srn.hh}.  We have defined our own class called {\sttXrlStaticRoutesNode} which is a child class of {\sttStaticRoutesNode}, {\stt XrlStdRouter} and {\stt XrlStaticRoutesTargetBase}classes.  We'llignore the {\stt StaticRoutesNode} class in this explanation, becauseit's specific to the \SRI process, but the important thing is that{\stt XrlStaticRoutesNode} is a child of the {\sttXrlStaticRoutesTargetBase} base class that was generated by the stubcompiler, and a child of the {\stt XrlStdRouter} base class.The constructor for our {\stt XrlStaticRoutesNode} class takes anumber of parameters which are specific to this particularimplementation, but it also takes a number of parameters that are usedin the constructor of the {\stt XrlStdRouter} base class.We also see from Listing \ref{lst:srn.hh} that our {\sttXrlStaticRoutesNode} class is going to implement the \\ {\sttstatic\_routes\_0\_1\_add\_route4()} method from the stub compilerwhich was a pure virtual method in the base class.\newpage\begin{lstlisting}[caption={Extracts from {\stt xorp/static\_routes/xrl\_static\_routes\_node.cc} %                                     \label{lst:srn.cc} } ]{}...#include "static_routes_node.hh"#include "xrl_static_routes_node.hh"...XrlStaticRoutesNode::XrlStaticRoutesNode(EventLoop&	eventloop,					 const string&	class_name,					 const string&	finder_hostname,					 uint16_t	finder_port,					 const string&	finder_target,					 const string&	fea_target,					 const string&	rib_target)    : StaticRoutesNode(eventloop),      XrlStdRouter(eventloop, class_name.c_str(), finder_hostname.c_str(),		   finder_port),      XrlStaticRoutesTargetBase(&xrl_router()),      ...     _xrl_rib_client(&xrl_router()),      ...{  ...}...XrlCmdErrorXrlStaticRoutesNode::static_routes_0_1_add_route4(    // Input values,    const bool&         unicast,    const bool&         multicast,    const IPv4Net&      network,    const IPv4&         nexthop,    const uint32_t&     metric){    string error_msg;    if (StaticRoutesNode::add_route4(unicast, multicast, network, nexthop,                                     "", "", metric, error_msg)        != XORP_OK) {        return XrlCmdError::COMMAND_FAILED(error_msg);    }    return XrlCmdError::OKAY();}\end{lstlisting}In Listing \ref{lst:srn.cc}, we see an extract from {\sttxorp/static\_routes/xrl\_static\_routes\_node.cc} where we haveactually implemented the {\stt XrlStaticRoutesNode} class.  The constructor for {\stt XrlStaticRoutesNode} passesa number of arguments to the {\stt XrlStdRouter} base class,and then passes to the constructor for the {\sttXrlStaticRoutesTargetBase} base class a pointer to this {\stt XrlStdRouter}base class (the return result for method {\stt xrl\_router()}).In addition, it initializes a lot of its own state (not shown).Note that if we were implementing a module that does not receive any XRLs (\ieit won't use the equivalent of {\stt XrlStaticRoutesTargetBase}), thenwe must call {\stt XrlStdRouter::finalize()} after {\stt XrlStdRouter}has been created.The complete implementation of {\sttXrlStaticRoutesNode::static\_routes\_0\_1\_add\_route4()} is shown.  Inthis case, most of the actual work is done elsewhere, but the generalidea is clear.  This is where we actually receive and process theincoming XRL request.  Once we have processed the request, we need to return from thismethod.  If this XRL had actually taken any return values, there wouldhave been parameters to the {\stt static\_routes\_0\_1\_add\_route4}method that were not {\stt const} references, and we would simply haveset the values of these variables before calling {\stt return} to passthe values back to the XRL caller.  In the case of \SRI however, noneof the XRLs return any values other than success or failure.  Wereturn {\stt XrlCmdError::OKAY()} if all is well, or {\sttXrlCmdError::COMMAND\_FAILED(error\_msg)} if something went seriouslywrong, passing back a human-readable string for diagnostic purposes.In general, if an error response needs to return machine-readableerror information, it is often better to return {\sttXrlCmdError::OKAY()} together with return parameters to indicate thatan error occurred and what actually happened, because if {\sttCOMMAND\_FAILED} is returned, the return parameter values are notpassed up to the caller application.\newpage%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\section{The Main Loop}\label{main}So far we've looked at how to define an XRL interface, how to compilethe C++ stubs for that interface, and how to define the actualcode that implements that interface.  Now we need to look at the main

⌨️ 快捷键说明

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