[Ns-developers] ns-3-nsc sysctl attribute support
Florian Westphal
fw at strlen.de
Mon Jul 7 08:23:39 PDT 2008
Hello ns-3 developers,
I've added a /sbin/sysctl like interface to NSC. It allows to change and
query an existing sysctl value while only using strings:
int sysctl_set(const char *name, const char *value);
int sysctl_get(const char *name, char *value, size_t len);
To retrieve a list of available sysctls, this method was added:
int sysctl_getnum(size_t idx, char *name, size_t len);
It will return -1 if the given index is out of range, so one can
iterate through the list, e.g.:
char buf[256]
for (i=0; sysctl_getnum(i, buf, sizeof(buf)) > 0 ;i++)
puts(buf);
Internally, the nsc stack cradle glue has a list of all known sysctl
values (patch http://git.breakpoint.cc/cgi-bin/gitweb.cgi?p=fw/nsc-fw.git;a=commitdiff;h=2f4fb096e18b78919edebff34adeeccb9de7d0de),
and the new code is merely a 'front-end' to the existing nsc sysctl-interface (i.e. the stacks sysctl(2) system call).
The advantage is that we avoid hooking into (most likely volatile) stack code. Also, this should be easy
to maintain since we'd only need to update the internal sysctl table.
On the other hand, its not yet clear if this interface is sufficient to support attributes
on the ns-3 side of things. My initial idea was to build an attribute tree when the stack
is being initialized (the following patch doesn't work at all, i'm quoting it because
it might be easier to follow what i tried to do from actual code than explanations):
diff -r c348e003e00d src/internet-stack/nsc-tcp-l4-protocol.cc
--- a/src/internet-stack/nsc-tcp-l4-protocol.cc Tue Jul 01 13:25:46 2008 +0200
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc Sat Jul 05 16:40:41 2008 +0200
@@ -22,7 +22,9 @@
#include "ns3/nstime.h"
#include "ns3/packet.h"
+#include "ns3/pointer.h"
#include "ns3/node.h"
+#include "ns3/string.h"
#include "tcp-header.h"
#include "ipv4-end-point-demux.h"
@@ -31,6 +33,7 @@
#include "nsc-tcp-l4-protocol.h"
#include "nsc-tcp-socket-impl.h"
+#include "sysctl-node.h"
#include "tcp-typedefs.h"
#include <vector>
@@ -123,6 +126,100 @@
m_softTimer.SetFunction (&NscTcpL4Protocol::SoftInterrupt, this);
m_softTimer.SetDelay (MilliSeconds (1000/hzval));
+
+ PointerValue x;
+ if (this->GetAttributeFailSafe ("NscSysctl", x)) {
+ m_nscStack->init(hzval);
+ //m_nscStack->set_diagnostic(1000);
+ m_softTimer.Schedule ();
+ return;
+ }
+
+ Ptr <SysctlNode> SysctlObject;
+ Ptr <SysctlNode> root = Create<SysctlNode> ();
+
+ // syctls are not a unique property of the TCP stack, this is WRONG.
+ // Furthermore, we might have another node using another stack where
+ // the tree looks completely different (and these trees must
+ // be kept separate)
+ //
+ // IOW, this is FUBAR, and needs to be re-tought. Stack initialization
+ // ought to be decoupled from nsc-tcp setup anyway for SCTP...
+ this->GetTypeId()
+ .SetParent<Ipv4L4Protocol> ()
+ .AddAttribute ("NscSysctl",
+ "Sysctl Hierarchy for this node",
+ PointerValue (root),
+ MakePointerAccessor (&NscTcpL4Protocol::m_node),
+ MakePointerChecker<SysctlNode> ())
+ ;
+// can't do that either, because we can't aggregate another object
+// which derives from ns3::Object.
+//node->AggregateObject (root) ;
+ std::cout << "available syscalls:\n";
+ char buf[256];
+ for (int i=0;
+ m_nscStack->sysctl_getnum(i, buf, sizeof(buf)) > 0;
+ i++)
+ {
+ std::string s = std::string (buf);
+
+ std::cout << "got " << buf << std::endl;
+ SysctlObject = root;
+ std::cout << "root addr " << root << "\n";
+ for (std::string::size_type idx;
+ (idx = s.find ('.')) != std::string::npos;
+ s = s.substr (idx+1))
+ {
+ std::string attr = s.substr(0, idx);
+
+ std::cout << "got token " << attr << std::endl;
+ PointerValue v;
+ std::cout << "call GetAttribute " << attr << "\n";
+ bool exists = SysctlObject->GetAttributeFailSafe (attr, v);
+ if (exists)
+ { // traverse to this node in the hierarchy.
+ Ptr<Object> obj = v.GetObject ();
+ // Ugh. Is there no other way than this turd? 8-(
+ Ptr <SysctlNode> convert = dynamic_cast<SysctlNode*>(PeekPointer(obj));
+ SysctlObject = convert;
+ continue;
+ }
+ // create new node and add it to this hierarchy
+ std::cout << "attribute " << attr << " doesnt exits, create it now" << std::endl;
+ Ptr <SysctlNode> newSysctlNode = Create<SysctlNode> ();
+ SysctlObject->Set (newSysctlNode);
+ SysctlObject->GetInstanceTypeId()
+ .AddAttribute (attr,
+ "sysctl node",
+ PointerValue (0),
+ MakePointerAccessor (&SysctlNode::Get, &SysctlNode::Set),
+ MakePointerChecker<SysctlNode> ())
+ ;
+ SysctlObject = newSysctlNode;
+ }
+
+ std::cout << "ObjectId " << SysctlObject->GetTypeId () << "\n";
+ // last leaf, it will contain a list of actual sysctl tuneables.
+ TypeId tid = SysctlObject->GetTypeId ();
+ std::cout << "last tid is " << tid << "\n";
+
+ // should this be StringValue?
+ // but then again, we can't use StringValue; because we need the FULL
+ // name of the sysctl as well (stored in buf) when we actually
+ // want to change a value on the NSC side.
+#if 1
+ Ptr<SysctlValue> value = Create<SysctlValue> (buf, "");
+ tid.AddAttribute (s, buf,
+ PointerValue (value),
+ MakePointerAccessor(&SysctlValue::Set, &SysctlValue::Get),
+ MakePointerChecker<SysctlNode> ())
+ ;
+#endif
+ }
+
m_nscStack->init(hzval);
//m_nscStack->set_diagnostic(1000);
As for SysctlNode and SysctlValue:
My idea was to create SysctlValue objects for 'actual' sysctls (i.e. a 'file' in /proc)
and SysctlNode objects for 'directories'.
I'd rather like to use StringValue attributes, but i somehow need to know to which syctl
the value needs to be applied to, so
class SysctlValue : public Object
{
public:
SysctlValue (const std::string &syctlName, const std::string &value);
void Set (Ptr<SysctlValue> p);
Ptr<SysctlValue> Get (void) const;
private:
std::string m_SysctlName;
};
stores the full sysctl name internally, so it can be used as the first argument in sysctl_set().
I've stopped working on this, because i'm way too confused about how this needs to be done properly.
In particular, do i have to add another AttributeAccessor, AttributeValue, etc; or is there a way
to use exisiting attribute types?
To avoid ending this mail in a too depressing manner: the Linux 2.6.26 port is now able to
run SCTP again. Now, how should that be integrated in ns-3?
Its easy to turn nsc-tcp into an nsc-sctp by changing
-const uint8_t NscTcpL4Protocol::PROT_NUMBER = 6;
+const uint8_t NscTcpL4Protocol::PROT_NUMBER = 132;
in nsc-tcp-l4-protocol.cc
and
- m_nscTcpSocket = tcp->m_nscStack->new_tcp_socket();
+ m_nscTcpSocket = tcp->m_nscStack->new_sctp_socket();
in nsc-tcp-socket-impl.cc.
My suggestion would be to first separate nsc-tcp and the nsc stack initialization
(i.e. try to put all the stack initialization and tcp unrelated things into a different file)
and then see about how the socket side of things can be done (I'd like to avoid copying the code,
maybe it would be best to add a nsc-socket-impl.cc and then have nsc-{tcp,sctp}-socket-impl.cc
delegate most of the work to it...)
Regards, Florian
More information about the Ns-developers
mailing list