5.4 The Classifier

The function of a node when it receives a packet is to examine the packet's fields, usually its destination address, and on occasion, its source address. It should then map the values to an outgoing interface object that is the next downstream recipient of this packet.

In ns, this task is performed by a simple classifier object. Multiple classifier objects, each looking at a specific portion of the packet forward the packet through the node. A node in ns uses many different types of classifiers for different purposes. This section describes some of the more common, or simpler, classifier objects in ns.

We begin with a description of the base class in this section. The next subsections describe the address classifierSectionsec:node:addr-classifier, the multicast classifierSectionsec:node:mcast-classifier, the multipath classifierSectionsec:node:mpath-classifier, the hash classifierSectionsec:node:hash-classifier, and finally, the replicatorSectionsec:node:replicator.

A classifier provides a way to match a packet against some logical criteria and retrieve a reference to another simulation object based on the match results. Each classifier contains a table of simulation objects indexed by slot number. The job of a classifier is to determine the slot number associated with a received packet and forward that packet to the object referenced by that particular slot. The C++ Classifier../ns-2/classifier.h (defined in ~ns/classifier.h) provides a base class from which other classifiers are derived.

        class Classifier : public NsObject {
        public:
                ~Classifier();
                void recv(Packet*, Handler* h = 0);
         protected:
                Classifier();
                void install(int slot, NsObject*);
                void clear(int slot);
                virtual int command(int argc, const char*const* argv);
                virtual int classify(Packet *const) = 0;
                void alloc(int);
                NsObject** slot_;       /* table that maps slot number to a NsObject /
                int nslot_;
                int maxslot_;
        };
The []classify method is pure virtual, indicating the class Classifier is to be used only as a base class. The []alloc method dynamically allocates enough space in the table to hold the specified number of slots. The []install and []clear methods add or remove objects from the table. The []recv method and the OTcl interface are implemented as follows in ~ns/classifier.cc:
        /*
         *objects only ever see "packet" events, which come either
         *from an incoming link or a local agent (i.e., packet source).
         */
        void Classifier::recv(Packet* p, Handler*)
        {
                NsObject* node;
                int cl = classify(p);
                if (cl \< 0 || cl \>= nslot_ || (node = slot_[cl]) == 0) {
                        Tcl::instance().evalf("%s no-slot %d", name(), cl);
                        Packet::free(p);
                        return;
                }
                node-\>recv(p);
        }

        int Classifier::command(int argc, const char*const* argv)
        {
                Tcl& tcl = Tcl::instance();
                if (argc == 3) {
                        /*
                         * $classifier clear $slot
                         */
                        if (strcmp(argv[1], "clear") == 0) {
                                int slot = atoi(argv[2]);
                                clear(slot);
                                return (TCL_OK);
                        }
                        /*
                         * $classifier installNext $node
                         */
                        if (strcmp(argv[1], "installNext") == 0) {
                                int slot = maxslot_ + 1;
                                NsObject* node = (NsObject*)TclObject::lookup(argv[2]);
                                install(slot, node);
                                tcl.resultf("%u", slot);
                                return TCL_OK;
                        }
                        if (strcmp(argv[1], "slot") == 0) {
                                int slot = atoi(argv[2]);
                                if ((slot \>= 0) || (slot \< nslot_)) {
                                        tcl.resultf("%s", slot_[slot]-\>name());
                                        return TCL_OK;
                                }
                                tcl.resultf("Classifier: no object at slot %d", slot);
                                return (TCL_ERROR);
                        }
                } else if (argc == 4) {
                        /*
                         * $classifier install $slot $node
                         */
                        if (strcmp(argv[1], "install") == 0) {
                                int slot = atoi(argv[2]);
                                NsObject* node = (NsObject*)TclObject::lookup(argv[3]);
                                install(slot, node);
                                return (TCL_OK);
                        }
                }
                return (NsObject::command(argc, argv));
        }
When a classifier []recv's a packet, it hands it to the []classify method. This is defined differently in each type of classifier derived from the base class. The usual format is for the []classify method to determine and return a slot index into the table of slots. If the index is valid, and points to a valid TclObject, the classifier will hand the packet to that object using that object's []recv method. If the index is not valid, the classifier will invoke the instance procedure []no-slot to attempt to populate the table correctly. However, in the base class []Classifier::no-slot prints and error message and terminates execution.

The []command method../ns-2/classifier.ccClassifier::command provides the following instproc-likes to the interpreter:



Subsections
Tom Henderson 2011-11-05