📄 xorpdev_101.tex
字号:
loop of a XORP process to see how these pieces all come together.In Listing \ref{lst:srn.main} the main pieces of {\sttxorp/static\_routes/xorp\_static\_routes.cc} are shown. Thesecomprise the entire initialization part and main loop of our \SRIprocess.First come the \#includes. Convention indicates that the firstof these ({\stt static\_routes\_module.h}) is a header file defining themodule name and version - thisinformation is used by later includes which will complain if thisinformation is not available. The content of {\stt static\_routes\_module.h}is very simple. It must define \verb=XORP_MODULE_NAME= and\verb=XORP_MODULE_VERSION=:\begin{lstlisting}[caption={Listing of {\stt xorp/static\_routes/static\_routes\_module.h} % \label{lst:srn.module} } ]{}#ifndef XORP_MODULE_NAME#define XORP_MODULE_NAME "STATIC_ROUTES"#endif#ifndef XORP_MODULE_VERSION#define XORP_MODULE_VERSION "0.1"#endif\end{lstlisting}Then we include the functionality from{\stt libxorp} that we'll need:\begin{itemize} \item {\stt libxorp/xorp.h}: generic headers that should always be included. \item {\stt libxorp/xlog.h}: XORP logging functionality. The convention is to use XLOG macros to log warnings and error messages, so we can redefine how logging if implemented in future without re-writing the code that uses logging. See Section~\ref{xlog} for more information about the XLOG facility. \item {\stt libxorp/debug.h}: XORP debugging functionality. \item {\stt libxorp/callback.hh}: XORP callback templates, needed to pass a handle into event handling code to be called later when an event occurs. \item {\stt libxorp/eventloop.hh}: the main XORP eventloop. \item {\stt libxorp/exceptions.hh}: standard exceptions for standard stuff - useful as a debugging aid.\end{itemize}Finally we include the definition of the class that implements the \SRXRL interface target class we just defined.In the processes {\stt main()} function, we intialize the {\stt xlog}logging functionality. Then (not shown) we handle command linearguments. The main part of this process occurs within a single {\stt try/catch}statement. The {\stt catch} part then handles any of the xorp standardexceptions that might be thrown. It is not intended that anyunhandled exceptions actually get this far, but if they do, then {\sttxorp\_catch\_standard\_exceptions()} will ensure that appropriatediagnostic information is available when the process expires. This isnot required, but it is good coding practice.The actual main loop that does all the work is in {\sttstatic\_routes\_main()}.First, the {\tt EventLoop} is created. Every XORP process should haveprecisely one {\tt EventLoop}. All processing in a XORP process isevent-driven from the eventloop. When the process is idle, it will beblocked in {\stt EventLoop::run()}. When an XRL request arrives, oran XRL response arrives, or a timer expires, or activity occurs on aregistered file handle, then an event handler will be called from theeventloop.Next we create an {\stt XrlStdRouter}. This is the object that willbe used to send and receive XRLs from this process. We pass it the{\stt EventLoop} object, information about the host and port where theXRL finder is located, and the XRL target name of this process: inthis case {\stt "static\_routes"}.Then we create an instance of the {\stt XrlStaticRoutesNode} class wedefined earlier to receive XRLs on the \SR XRL target interface.Inside this object there will be the corresponding {\stt XrlStdRouter}object for sending and receiving XRLs from this process.We pass to {\stt XrlStaticRoutesNode} the following:\begin{itemize} \item The {\stt EventLoop} object. \item The XRL target name of this process: in this case {\stt "static\_routes"}. \item Information about the host and port where the XRL finder is located. \item Information about the names of other XRL targets we need to communicate with: the Finder, the FEA, and the RIB.\end{itemize}Before we proceed any further, we must give the XrlStdRouter time toregister our existence with the Finder. Thus we call {\sttwait\_until\_xrl\_router\_is\_ready()}.\newpage\begin{lstlisting}[caption={Extracts from {\stt xorp/static\_routes/xorp\_static\_routes.cc} % \label{lst:srn.main} } ]{}//// XORP StaticRoutes module implementation.//#include "static_routes_module.h"#include "libxorp/xorp.h"#include "libxorp/xlog.h"#include "libxorp/debug.h"#include "libxorp/callback.hh"#include "libxorp/eventloop.hh"#include "libxorp/exceptions.hh"#include "xrl_static_routes_node.hh"...static voidstatic_routes_main(const string& finder_hostname, uint16_t finder_port){ // // Init stuff // EventLoop eventloop; // // StaticRoutes node // XrlStaticRoutesNode xrl_static_routes_node( eventloop, "static_routes", finder_hostname, finder_port, "finder", "fea", "rib"); wait_until_xrl_router_is_ready(eventloop, xrl_static_routes_node.xrl_router()); // Startup xrl_static_routes_node.startup(); // // Main loop // while (! xrl_static_routes_node.is_done()) { eventloop.run(); }}intmain(int argc, char *argv[]){ int ch; string::size_type idx; const char *argv0 = argv[0]; string finder_hostname = FinderConstants::FINDER_DEFAULT_HOST().str(); uint16_t finder_port = FinderConstants::FINDER_DEFAULT_PORT(); // // Initialize and start xlog // xlog_init(argv[0], NULL); xlog_set_verbose(XLOG_VERBOSE_LOW); // Least verbose messages // XXX: verbosity of the error messages temporary increased xlog_level_set_verbose(XLOG_LEVEL_ERROR, XLOG_VERBOSE_HIGH); xlog_add_default_output(); xlog_start();... // // Run everything // try { static_routes_main(finder_hostname, finder_port); } catch(...) { xorp_catch_standard_exceptions(); } // // Gracefully stop and exit xlog // xlog_stop(); xlog_exit(); exit (0);}\end{lstlisting}Finally we're ready to go. We set our internal state as ready, andenter a tight loop that we will only exit when it is time to terminatethis process. At the core of this loop, we call {\sttEventLoop::run()} repeatedly. {\stt run()} will block when there areno events to process. When an event is ready to process, the relevantevent handler will be called, either directly via a {\stt callback} orindirectly through one of the XRL stub handler methods we definedearlier. Thus if another process calls the \\{\stt finder://static\_routes/static\_routes/0.1/add\_route4} XRL, thefirst we'll know about it is when {\stt XrlStaticRoutesNode::static\_routes\_0\_1\_add\_route4()} is executed.\newpage%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\section{Calling XRLs on the RIB}\label{rib}So far we have seen how we define an XRL interface, how we implementthe target side of such an interface, and how the main loop of a XORPprocess is structured. In the case of \SRI, we can now receive XRLsinforming us of routes. The \SRI process will do some checks andinternal processing on these routes (such as checking that they go outover a network interface that is currently up). Finally it willcommunicate the remaining routes to the RIB process for use by theforwarding plane. We will now examine how we send these routes to theRIB.If we look in {\stt xorp/xrl/interfaces} we find the file {\sttrib.xif} which defines the XRLs available on the {\stt rib} interface.Listing \ref{lst:rib.xif} shows some extracts from this file. Aswe've been following through the {\stt add\_route4} XRL, we'll againlook at that here. We'll also look at the {\stt lookup\_route\_by\_dest4}XRL because this is an example of an XRL that returns some data, althoughthis particular XRL is not actually used by the \SRI process. It isalso worth noting in passing that the RIB requires a routing protocol(such as \SRI) to call {\stt add\_igp\_table4} before sending routesto the RIB, or the RIB will not know what to do with the routes.As we saw with the {\stt static\_routes.xif} file, the {\stt rib.xif}file is processed by a python script to produce the files {\sttrib\_xif.hh} and {\stt rib\_xif.cc} in the {\stt xorp/xrl/interfaces}directory which are then compiled and linked to produce the {\sttlibribxif.la} library. This library provides a class definition whichdoes all the work of marshalling C++ arguments into XRLs, sending theXRL to the RIB process, receiving the response, and calling therelevant callback in the caller process with the response data.Listing \ref{lst:ribxif.hh} shows some extracts from {\sttrib\_xif.hh} so we can see what the C++ interface to this librarylooks like. The library implements a class called {\sttXrlRibV0p1Client}. To use this code, we must first create an instanceof this class, calling the constructor and supplying a pointer to an{\stt XrlSender}. Typically such an XrlSender is an instance of an{\stt XrlRouter} object. In Listing \ref{lst:srn.hh} we can see that our implementation of class{\stt XrlStaticRoutesNode} actually defined an instance of {\sttXrlRibV0p1Client} called {\stt \_xrl\_rib\_client} as a membervariable, so this object is created automatically when our main loopcreates {\stt xrl\_static\_routes\_node} in Listing\ref{lst:srn.main}. In Listing \ref{lst:srn.cc} we can see that wepassed {\stt xrl\_router} into the constructor for {\stt\_xrl\_rib\_client}.So, once everything else has been initialized, we'll have accessto {\stt \_xrl\_rib\_client} from within {\sttxrl\_static\_routes\_node}. Now, how do we make use of this generatedcode? The answer is simple: to send a route to the RIB we simply call{\stt \_xrl\_rib\_client.send\_add\_route4()} with the appropriateparameters, and the generated library code will do the rest. We cansee this in Listing \ref{lst:sr.send}, where this code is actually used.The only real complication here is related to how we get the responseback from the XRL. Recall that {\stt\_xrl\_rib\_client.send\_add\_route4()} will return immediately with a localsuccess or failure response, before the XRL has actually beentransmitted to the RIB. Thus we need to pass a {\it callback} in to{\stt send\_add\_route4()}. This callback will wrap up enough state sothat when the response finally returns to the XrlRouter in the \SRIprocess, it will know which method to call on which object with whichparameters so as to send the response to the right place.We can see in {\stt XrlRibV0p1Client} (Listing \ref{lst:srn.hh}) thatthe type of the callback is:\\{\stt XorpCallback1<void, const XrlError\&>::RefPtr}\\This defines a callback function that returns {\stt void} and whichtakes one argument of type {\stt const XrlError\&}. If we look inListing \ref{lst:sr.send} we seen that the method {\sttXrlStaticRoutesNode::send\_rib\_route\_change\_cb()} fits exactly thesecriteria. This is the method we are going to use to receive theresponse from our XRL request.\newpage\begin{lstlisting}[caption={Extracts from {\stt xorp/xrl/interfaces/rib.xif} % \label{lst:rib.xif} } ]{}interface rib/0.1 {... /** * Add/delete an IGP or EGP table. * * @param protocol the name of the protocol. * @param target_class the target class of the protocol. * @param target_instance the target instance of the protocol. * @param unicast true if the table is for the unicast RIB. * @param multicast true if the table is for the multicast RIB. */ add_igp_table4 ? protocol:txt \ & target_class:txt & target_instance:txt\ & unicast:bool & multicast:bool... /** * Add/replace/delete a route. * * @param protocol the name of the protocol this route comes from. * @param unicast true if the route is for the unicast RIB. * @param multicast true if the route is for the multicast RIB. * @param network the network address prefix of the route. * @param nexthop the address of the next-hop router toward the * destination. * @param metric the routing metric. * @param policytags a set of policy tags used for redistribution. */ add_route4 ? protocol:txt & unicast:bool & multicast:bool \ & network:ipv4net & nexthop:ipv4 & metric:u32 \ & policytags:list replace_route4 ? protocol:txt & unicast:bool & multicast:bool \ & network:ipv4net & nexthop:ipv4 & metric:u32 \ & policytags:list delete_route4 ? protocol:txt & unicast:bool & multicast:bool \ & network:ipv4net... /** * Lookup nexthop. * * @param addr address to lookup. * @param unicast look in unicast RIB. * @param multicast look in multicast RIB. * @param nexthop contains the resolved nexthop if successful, * IPv4::ZERO otherwise. It is an error for the unicast and multicast * fields to both be true or both false. */ lookup_route_by_dest4 ? addr:ipv4 & unicast:bool & multicast:bool \ -> nexthop:ipv4}\end{lstlisting}\newpage\begin{lstlisting}[caption={Extracts from {\stt xorp/xrl/interfaces/rib\_xif.hh} % \label{lst:ribxif.hh} } ]{}class XrlRibV0p1Client {public: XrlRibV0p1Client(XrlSender* s) : _sender(s) {}... typedef XorpCallback1<void, const XrlError&>::RefPtr AddRoute4CB; /** * Send Xrl intended to: * * Add/replace/delete a route. * * @param dst_xrl_target_name the Xrl target name of the destination. * @param protocol the name of the protocol this route comes from. * @param unicast true if the route is for the unicast RIB. * @param multicast true if the route is for the multicast RIB. * @param network the network address prefix of the route. * @param nexthop the address of the next-hop router toward the * destination. * @param metric the routing metric. * @param policytags a set of policy tags used for redistribution. */ bool send_add_route4( const char* dst_xrl_target_name, const string& protocol, const bool& unicast, const bool& multicast, const IPv4Net& network, const IPv4& nexthop, const uint32_t& metric, const XrlAtomList& policytags, const AddRoute4CB& cb );... typedef XorpCallback2<void, const XrlError&, const IPv4*>::RefPtr LookupRouteByDest4CB; /** * Send Xrl intended to: * * Lookup nexthop. * * @param dst_xrl_target_name the Xrl target name of the destination. * @param addr address to lookup. * @param unicast look in unicast RIB. * @param multicast look in multicast RIB.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -