Hi All,
I've hit a road block that I'm hoping people with better C/macro fu can
help me with. It also may be the case that what I'm trying to do can't
be done, so I welcome alternative suggestions as well.
The problem:
I'm working on a KPI to modularise congestion control support in the
kernel (overview of KPI is visible in [1]). So far, I've been focused
solely on TCP, but I want to have the framework generalise to be able to
share congestion control algorithms between other congestion aware
transports e.g. SCTP, DCCP.
To achieve this, I need to pass congestion control information into the
hook functions in a protocol agnostic way. The current KPI passes the
tcpcb ptr and this works nicely, but obviously doesn't help.
The cleanest option as I see it is to embed a new CC specific struct in
the appropriate TCP and SCTP structs, and pass this in to the KPI. I
started down this road and quickly stopped - the amount of code churn
this will cause in the TCP and SCTP stacks is to my mind far to
intrusive, at least for an initial import of the framework.
So the next idea I've been trying to prototype was to pass a union of
the various protocol struct types into the KPI and then use macro magic
to allow the CC algorithms to access commonly named variables across the
different transport struct types. It would require vars to have the same
name, which would still mean some code churn, but less than the first
option. Here are the basic bits I'm currently working with:
struct cc_var {
uint16_t type;
union {
struct tcpcb *tcp;
struct sctp_nets *sctp;
} ccvc;
};
All function ptrs in struct cc_algo [1] are modified to accept a "struct
cc_var *ccv".
In an algorithm implementation e.g. NewReno [2], I then want to be able
to do things like this with the fictitious CCVC() macro:
void
newreno_ack_received(struct cc_var *ccv)
{
u_int cw = CCVC(ccv)->snd_cwnd;
...
CCVC(ccv)->snd_cwnd = blah;
}
So far I haven't found a way to achieve the above, and the best I've
come up (with help) is this:
#define CCV_DO(ccv, what) \
( \
(ccv)->type == IPPROTO_TCP ? (ccv)->ccvc.tcp->what : \
(ccv)->ccvc.sctp->what \
)
which can be used like this:
void
newreno_ack_received(struct cc_var *ccv)
{
u_int cw = CCV_DO(ccv, snd_cwnd);
...
CCVC(ccv, snd_cwnd = blah);
}
Of course, this falls apart if you try do this for example:
CCVC(ccv, snd_cwnd = min(blah, bleh));
So... I'm sure there are some good ideas out there and would really
appreciate hearing about them.
Cheers,
Lawrence
PS: Cookie will only be awarded after complete working solution has been
demonstrated and verified in my development branch!
[1]
http://svn.freebsd.org/viewvc/base/projects/tcp_cc_head/sys/netinet/cc.h?view=markup
[2]
http://svn.freebsd.org/viewvc/base/projects/tcp_cc_head/sys/netinet/cc_newreno.c?view=markup
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"