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

📄 implementation.tex

📁 xorp源码hg
💻 TEX
📖 第 1 页 / 共 4 页
字号:
Internally, the dispatcher has a map from a key to a callback. The keyrepresents the requested operation and the types of arguments in order. If anentry is not found, it means the permutation is invalid and an exception isthrown. On success, the callback is executed and the return value is passed tocaller (double dispatch).There must be a way to register callbacks with the dispatcher in order to addentries to the map. This is done via the add functions:\begin{verbatim}    template<class T, Element* (*funct)(const T&)>    void add(const UnOper& op);    template<class L, class R,              Element* (*funct)(const L&,const R&)>    void add(const BinOper& op);\end{verbatim}Currently there is no way to add n-ary callbacks, but it is trivial to do so, ifthe function will take an ArgList as a parameters instead of explicitly expandedparameters. Notice that the template parameters are concrete types of theelements for the operation being added.It is important to have only one global map, and to register the callbacksbefore the map is used. The map is therefore static, and the callbacks areregistered via a RegisterOperations class.Arguments of the Element NULL type are treated as a special case. By definition,any operation which has a NULL argument will return a new NULL element. Thisbecomes useful, for example, when testing if a IPv4 address equals the next-hopof an IPv6 route (remember that a NULL element will be returned by VarRW in thiscase). Returning true or false will be misleading, thus the choice is returninganother NULL element.\subsubsection{Register operations with dispatcher}The dispatcher class has a static member of RegisterOperations initialized rightafter the map. This will ensure that the RegisterOperations constructor will becalled right after the map initialization, and only once (static).The sole purpose of the RegisterOperations is to initialize the dispatcher map.In fact, it only has a constructor which will perform the adds to thedispatcher. If a new operation needs to be added to the whole policy framework it should beenough to add it in the RegisterOperations class. If this operation requires anew symbol to be used in the configuration, then the appropriate modificationsneed to be done in the front end and back end lexers and grammars. Also, a newoperation class needs to be created to represent it. To increase flexibility,operations may be created via a factory in the future which would not requiremodification of the backend possibly.Notice that sometimes it suffices to add different permutations of arguments andexisting operations to the dispatcher. This will in essence change the ``dynamicgrammar'' and what permutations of argument types / operations are allowed(possibly overloading existing operations).\subsection{Details on ElementFactory}With a flexible dispatcher like the one described above, elements maytheoretically be created via it. It should be possible to simply register anoperation CreateElement which takes a string element as argument.The ElementFactory works almost exactly as the dispatcher, but is different innature. For this reason I kept the two separate.  The dispatcher executes basedon the type of arguments. The factory creates based on the value of arguments.Note that subtle difference, although the argument passed to the factoryactually is a type identifier of the element, the factory treats it a value, nota type.Elements may be registered with the factory in a similar way as with thedispatcher:\begin{verbatim}    typedef Element* (*Callback)(const char*);    void add(const string& key, Callback cb);\end{verbatim}{\em Key} represents the type of the element (its string representation). The callbackfunction will construct the element via a c-style string. If the pointer is NULL,a default value should be assigned to the newly created element.  Defaultinitialized elements are extensively used by the front end semantic checker.As with the dispatcher, the map is static and a RegisterElements class isprovided for initialization.Adding elements to the factory simply requires registering them and creating aderived version of the Element class. Currently, the lexer does all typeidentification, so that must be modified with a regular expression to match thenew element type. There is no run-time ``type guessing'' mechanism, which Ithink should be added. The new element must be added in the grammar too.A utility template ElemAny is provided which may help in creating new elements.Currently IPv4/6 and others are implemented using this wrapper.\section{Operators}Operators were met in the dispatcher, both in the run and add methods. Theinterface for operators is:\begin{verbatim}    virtual unsigned arity() const = 0;    virtual string str() const = 0;\end{verbatim}Each operator has an arity associated (the number of arguments it takes). Thisis useful for asserting correctness of argument lists. To check if user suppliedright number of arguments. Each operator is string representable.Again, the justification is that the compiled programs need to be sent in astring form to the backend. Also, the user will type them in text (hopefully) inthe configuration file. So there must be a string representation. The stringrepresentation must be unique! The dispatcher uses it for the creation of thekey in the map lookup for example.There are two more utility base classes for operators, namely BinOper and UnOperwhich define the arity to 2 and 1 respectively. This way new binary and unaryoperators may be derived without the need to worry about arity. It also helpsgrouping operations in a hierarchy.\section{Policy backend internals} Having the ability to create elements andperform operations on them makes thedesign of the backend filter conceptually easy. Backend filters are implementedas a simple stack machine. They read a pseudo-code assembly like program, andexecute it. No semantic checks are done, thus exceptions may be thrown on bogusprograms (although they should not reach the filter in the first place).The parse of the program will result in a list of Policy Instructions. A policyinstruction is simply a container of term instructions, which is itself acontainer of instructions. Basically, the result will be having a structure ofordered instruction classes.All instructions are derived from a same base and implement the Visitor designpattern as proposed by Alexandrescu. This allows traversing the structure withdifferent implementations (visitors). The only drawback of using visitors isthat if new instructions are added, all the visitors need to be updated.However, in this case instructions will change little over time, and only onevisitor is present anyway.The visitor present is in fact the interpreter of the program. The executionvisitor IvExec.\subsection{Backend execution visitor}The execution visitor is generic enough to support N-ary instructions. It alsosupports the creation of any element. Thus if a new element is registered withthe factory, the visitor remains unchanged. The same goes for operations,although the backend parser will need to cope with creating the properinstructions.The interpreter will use the VarRW interface to load and store route attributes.It will also need an entity called the SetManager to reference sets. Ideally,sets should be transferred independently from policies and managed on their own.Sets may be sharded among policies, so having one copy both eases maintenanceand saves memory. This is currently not the case however. Sets are bound toprograms.The only instruction which is treated as a special case is the REGEX. Anyelement may be compared to a regular expression. Recall that all elements have astring representation, so a regex match will always be possible.The ON\_FALSE\_EXIT will exit the current term if a false or null is on the topof the stack. Execution will resume on the next term. It does not pop elementsfrom the stack.If a STORE operation needs to be executed, and the argument is a null element,the operation is silently discarded.An IvExec will return a {\em flow action} from its execution. Currently it maybe to accept the route, reject it, or perform the default action. Defaultactions should be user settable and changeable from within policies. Theycurrently are not, but it should be easy to add a variable named {\em defaultaction} and allow the user to modify it.\subsection{Set manager}The Set manager owns all the sets of a filter. It is responsible for theirmaintenance and memory management. A set manager is similar to the VarRW fromthe IvExec point of view. The only difference is that the IvExec will only readsets and never write to them.The IvExec refers to a set via its name, and the set manager will return thecorresponding ElemSet if it exists. Sets act like pointers in the mini languageand the SetManager is responsible for dereferencing them.\section{Policy manager: the front end}The front end needs to cope with serval tasks:\begin{itemize}\item sanity check user configuration and requests.\item generate code for policies.\item track configuration changes and apply modifications.\item manage backend filters.\item manage the RIB redistribution map.\end{itemize}The hardest tasks probably lie in sanity checks and trying to reconfigurefilters the least possible on configuration changes. If a filter isreconfigured, routes will need to be pushed, which is an expensive operation.\subsection{Dependency tracking and sanity checks}Most of the sanity checks involve tracking dependencies between protocols andpolicies, and policies and sets. The policy manager should not allow a user todelete a set which is in use for example. Also, the policy manager should notallow a user to create a policy which already exists.In general, policies depend on sets. If a policy uses a set, the set may not bedeleted. Also, policies instantiations via the import or export directive dependon the policies which they refer to. Thus, a policy may not be deleted if it isbeing used for an import or export.Similarly, policies and sets need to be defined before they may be referenced.This may be avoided, but for simplicity forward definition is a requirement.To allow dependency tracking, a Dependency template is used. It owns pointers toobjects. These objects are referred to by names, and also have a dependency listwhich refers to who is currently using them. It does not mean the object itselfdepends on anything --- the list contains who depends on the object. Thistemplate is used to track dependencies both in policies and sets.\subsection{Code generation}The parsing implementation is similar to the backend. All statements are parsedand result in a PolicyStatement which contains a list of Terms which contain alist of nodes.All nodes implement the visitor interface. The usefulness of visitors becomesapparent in this case. At least two passes need to be done on the nodes(although they may probably be done in one go). First a semantic check, and thenthe code generation pass.Code generation and semantic checks are done only on instantiated policies. Apolicy which is not used is totally ignored and no possible errors are reported.This may be fixed by having a generic semantic check visitor pass through thepolicy to try and see if it makes at least {\em any} sense.\subsubsection{Semantic check pass}The nodes must first be semantically checked as the static grammar does only aminimum. The real semantic check resides in actually trying to execute thepolicy and see if the combination of types and operations is supported by thedispatcher. This check is done by executing the nodes of the parse tree directly.Execution is done on all nodes (all flows of the program).A special VarRW called the SemanticVarRW will try emulating the protocolrequested by the execution visitor. This is done via the VarMap configuration.The SemanticVarRW knows exactly what type is expected from a certain variable.Also, misspelling of variable names or invalid reads/writes will be caught atthis time.The existence of sets will be checked too. Although set errors will probablybe caught when the SetDep visitor is executed to track policy and setdependencies.\subsubsection{Code generation pass}There are three different visitors which generate code depending on how the policy

⌨️ 快捷键说明

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