Date: Sat, 15 Dec 2007 10:17:50 -0800 From: Sam Leffler <sam@errno.com> To: Robert Watson <rwatson@freebsd.org> Cc: Kip Macy <kip.macy@gmail.com>, FreeBSD Current <freebsd-current@freebsd.org>, freebsd-arch@freebsd.org Subject: Re: pending changes for TOE support Message-ID: <47641A4E.5050106@errno.com> In-Reply-To: <20071215152959.V85668@fledge.watson.org> References: <b1fa29170712121303x537fd11fj4b8827bb353ad8e4@mail.gmail.com> <b1fa29170712150057m690bd36bm7a1910969e92293b@mail.gmail.com> <20071215100351.Q70617@fledge.watson.org> <20071215152959.V85668@fledge.watson.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Robert Watson wrote: > > On Sat, 15 Dec 2007, Robert Watson wrote: > >> More comments to follow. > > Some more, back to tcp_offload.c which I didn't look at last time around: > > + ifp = rt->rt_ifp; > + tdev = TOEDEV(ifp); > + if (tdev == NULL) > + return (EINVAL); > + > + if (tdev->tod_can_offload(tdev, so) == 0) > + return (EINVAL); > > I sort of expected to see a if_capenable check for TOE here, but I > guess it doesn't make much difference if the flag is going to be > checked at the lower level. However, in the case of things like TCP > checksum offload, we do do the check at the higher level, so it > wouldn't be inconsistent to do that. > > BTW, could you prepare similar comments for toedev.h? > > +struct toe_usrreqs tcp_offload_usrreqs = { > + .tu_send = tcp_output, > + .tu_rcvd = tcp_output, > + .tu_disconnect = tcp_output, > + .tu_abort = tcp_output, > + .tu_detach = tcp_offload_detach_noop, > + .tu_syncache_event = tcp_offload_syncache_event_noop, > +}; > > This structure seems to introduce quite a bit more indirection for > non-offloaded cases than before, especially to do things like this: > > +static void > +tcp_offload_syncache_event_noop(int event, void *toepcb) > +{ > +} > > The compiler can't compile these out because it likely doesn't do much > in the way of function pointer analysis, and probably shouldn't. > However, it leaves quite a few code paths heavier weight than before. > I think I'd prefer a model in which a TF_OFFLOAD flag is set on the > tcpcb and then we conditionally invoke tu_foo as a result. I.e.,: > > static __inline int > tcp_gen_send(struct tcpcb *tp) > { > > #ifndef TCP_OFFLOAD_DISABLE > if (tcp->f_flag & TF_OFFLOADED) > return (tp->t_tu->tu_send(tp)); > else > #endif > return (tcp_output(tp)); > } > > This would compile to a straight call to tcp_output() when offloading > isn't compiled in, and when it is compiled in and offloading isn't > enabled, we do a simple flag check rather than invoking a function via > a series of pointers. I suggested Kip explore this technique as an alternative to having the inlines that check whether a socket is marked for offload or not (tradeoff indirect function call vs conditionals). My comment to him was that I find it can make code more intuitive. But with the common case being empty functions it's probably not a great option as the compiler cannot optimize it out. > > Back to tcp_offload.h: > > +#define SC_ENTRY_PRESENT 1 /* 4-tuple already present */ > +#define SC_DROP 2 /* connection was timed out */ > > I think you should give these a different prefix, since they're part > of the interface between the syncache and offload, and SC_ generally > are flags used internal to the syncache. Later you use TCP_OFFLOAD_ > as the prefix, so that may be appropriate here also. > > +#define TCP_OFFLOAD_LISTEN_OPEN 1 > +#define TCP_OFFLOAD_LISTEN_CLOSE 2 > + > +typedef void (*tcp_offload_listen_fn)(void *, int, struct tcpcb > *); > +EVENTHANDLER_DECLARE(tcp_offload_listen, tcp_offload_listen_fn); > > Here and with the syncache interface, it seems like you're adding new > operations as modes to functions, whereas elsewhere you're adding > multiple functions. There isn't too much difference, but I think I'd > rather see a slightly wider interface (i.e., more functions) and avoid > flags that change the semantics of particular functions. That is to > say: tu_syncache_add and tu_syncache_drop, and likewise > tcp_offload_listen and tcp_offload_unlisten (or something similar). > > +int tcp_offload_connect(struct socket *so, struct sockaddr *nam); > > This prototype appear not to be documented. > > +/* > + * The tcp_gen_* routines are wrappers around the toe_usrreqs calls, > + * in the non-offloaded case they translate to tcp_output. > > Not really sure about the _gen_ naming, but not sure I have a better > suggestion in mind just yet -- maybe _output_ since they control > output. I'm not entirely thrilled that all of these become inline > functions in include files, although since a couple are used in > multiple tcp*.c files, it may be the least bad of the options. My > comments above about possibly restructuring this to avoid lots of > indirection for non-offloaded case strengthen the argument for > inlining, however. > > +#ifndef TCP_OFFLOAD_DISABLE > > I notice you've renamed the option, and I like the new name a lot > better. However, I also notice that it doesn't seem to appear in > conf/options or conf/files. Could you make sure to add it? > > +/* > + * The socket has not been marked as "do not offload" > + */ > +#define SO_OFFLOADABLE(so) ((so->so_options & SO_NO_OFFLOAD) == 0) > > I find myself wondering if the offload option should be a TCP socket > option rather than a socket-layer option, but don't have strong > feelings about this. > > What do you intend the policy model to be for enabling TOE, in > general? That if the TOE capability is available and the TOE > capability is enabled, all TCP sockets via the enabled interface will > be offloaded unless SO_NO_OFFLOAD is set? Are you currently > anticipating enabling the capability by default? > > Nitpick on style: > > + /* disconnect offload device, if any */ > > Comments that are sentences should begin with an upper case letter and > end with a period. :-) And another one: > > +#ifdef TCP_OFFLOAD_DISABLE > +#define TOEPCB_SET(sc) (0) > +#else > +#define TOEPCB_SET(sc) ((sc)->sc_toepcb != NULL) > +#endif > + > + > > Too many blank lines there. > > I've noticed that in quite a few places, we prefer X_ISSET() to test > for a set flag or other condition, in order to prevent confusion with > X_SET() assigning a value. I think that's pretty sensible, and should > do it more myself, so encourage you to do the same >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?47641A4E.5050106>