\documentclass{slides}
\usepackage{graphics}
\setlength{\topmargin}{0pt}
\setlength{\headheight}{0pt}
\setlength{\headsep}{0pt}
\setlength{\oddsidemargin}{0pt}
\setlength{\evensidemargin}{0pt}
\setlength{\textwidth}{6in}
\setlength{\textheight}{6in}
\begin{document}
\newcommand{\listinit}{\setlength{\labelwidth}{0.20in}\setlength{\itemsep}{0.15in}\setlength{\parsep}{0in}\setlength{\topsep}{0in}}

\Large
\begin{slide}
\begin{center}
Porting Kernel Code\\
to Four BSDs and Linux\\
\vspace{0.5in}
Craig Metz\\
\vspace{0.5in}
June 10, 1999
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Overview}\\
\begin{list}{$\bullet$}{\listinit}
\item Introduction/Background\\
\item Should You Port It?\\
\item General Techniques\\
\item The {\tt nbuf}\\
\item Conclusions\\
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Introduction}
\begin{list}{$\bullet$}{\listinit}
\item This talk is based on my group's experience with the NRL IPv6+IPsec code.
\item IPv6 code runs on BSD/OS, FreeBSD, NetBSD, OpenBSD.
\item IPsec code runs on those plus Linux (port in progress).
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Introduction}
\begin{list}{$\bullet$}{\listinit}
\item Porting kernel code is not a new idea.
\item {\tt de} driver $\rightarrow$ all four BSDs.
\item Linux x87 emulator $\rightarrow$ *BSD
\item BSD 53c{\em xxx} driver $\rightarrow$ Linux
\item BSD network code $\rightarrow$ sundry
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Introduction}
\begin{list}{$\bullet$}{\listinit}
\item Yet, there's a big resistance to porting kernel code.
\item An overemphasis on the\\ differences between systems.
\item Standards put constraints on the differences.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Should You Port It?}\\
\begin{list}{$\bullet$}{\listinit}
\item Be realistic. You can't port everything.
\item Some things depend too\\
heavily on the original\\
system.
\item It would be less effort to just rewrite those.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Should You Port It?}\\
\begin{list}{$\bullet$}{\listinit}
\item Some problems on one\\
system don't exist on\\
another.
\item Or are being solved by\\
somebody else.
\item Pick problems that need you to solve them.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Should You Port It?}\\
\begin{list}{$\bullet$}{\listinit}
\item Making useful features\\
available on more systems is a good thing.
\item Making systems do the same thing similarly is good.
\item You don't have to have 99\% code sharing to be useful.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Techniques}\\
\begin{list}{$\bullet$}{\listinit}
\item Use what you (hopefully)\\
already know from userland.
\item But bad code is tolerated less by kernel people.
\item I'll mention a few points here.
\item See the paper for more.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Techniques}\\
\begin{list}{$\bullet$}{\listinit}
\item Organize code carefully.
\item You'll go crazy if you don't.
\item Our tree has seven pieces:
\begin{list}{$\bullet$}{\listinit\setlength{\topsep}{0.2in}}
\item One for each system (x5)
\item One shared by all BSD
\item One shared by all
\end{list}
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Techniques}\\
\begin{list}{$\bullet$}{\listinit}
\item Abstraction: Macros, higher-level functions, etc.
\item Conditionalizing: A maze of twisty {\tt ifdef} statements
\item Prefer the former, but\\
prefer doesn't mean always
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Techniques}\\
\begin{list}{$\bullet$}{\listinit}
\item Linux: {\tt kmalloc(size, flags)}
\item BSD: {\tt malloc(size, type, wait)}
\item Abstraction: {\tt OSDEP\_MALLOC(size)}
\item For similar things, trade off
unneeded features for\\
generality
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Techniques}\\
\begin{list}{$\bullet$}{\listinit}
\item Linux: {\tt \_\_u32}
\item BSD: {\tt u\_int32\_t}
\item POSIX: {\tt uint32\_t}
\item Same thing, different names.
\item We make the POSIX names available in all systems and use those.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\vspace{\baselineskip}
\begin{list}{$\bullet$}{\listinit}
\item Linux: {\tt struct sk\_buff}
\item BSD: {\tt struct mbuf}
\item No {\tt \#define} for this one.
\item Deeper differences require more work to handle.
\item We created an abstracted buffer that can encapsulate.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\begin{list}{$\bullet$}{\listinit}
\item Use what we like about each
\item Linux: Packet data is\\
contiguous in memory
\item Linux: Payload data copied into place, headers built out
\item BSD: Small header size
\item BSD: Few extraneous fields
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\begin{list}{$\bullet$}{\listinit}
\item We want to convert native to {\tt nbuf}, work in the {\tt nbuf}, and
convert from {\tt nbuf} back to the native buffer
\item Common-case performance {\bf must} be good
\item Copying the data is out
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\begin{list}{$\bullet$}{\listinit}
\item We can avoid copies if two ``fast path'' conditions hold:
\item Enough space to meet any expansion needs before and after the packet
\item Packet data is contiguous in memory
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\begin{list}{$\bullet$}{\listinit}
\item Expansion space can be\\
arranged for by slightly\\
changing the places data is copied into native buffers.
\item We don't do a good job of this right now.
\item That turns out not to hurt much.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\begin{list}{$\bullet$}{\listinit}
\item Linux: packet data always contiguous in memory
\item BSD: usually if {\tt len} $< 100$ or $208 <$ {\tt len} $\le 2048$.
\item Most real IP packets fall into those size ranges.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\begin{list}{$\bullet$}{\listinit}
\item We define conversion\\
functions for each system.
\item Linux: {\tt skbton()}, {\tt ntoskb()}
\item BSD: {\tt mton()}, {\tt ntom()}
\item They really do use the fast path most of the time.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf The {\tt nbuf}}\\
\begin{list}{$\bullet$}{\listinit}
\item The point of the exercise: Our IPsec ESP and AH code works exclusively
with {\tt nbuf}s instead of native buffers.
\item Common properties makes the code simpler.
\item Maybe faster, too.
\end{list}
\end{center}
\end{slide}


\begin{slide}
\begin{center}
{\bf Conclusions}\\
\begin{list}{$\bullet$}{\listinit}
\item 20\% to 40\% of the NRL code is system-specific
\item 80\% to 60\% of the NRL code is shared
\item Less code sharing than in is common in userland
\item Still, that's pretty good
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Conclusions}\\
\vspace{\baselineskip}
The point of this talk:\\
\begin{list}{$\bullet$}{\listinit}
\item {\bf Sometimes} it can be done.
\item {\bf Sometimes} it's the right thing.
\item Set reasonable expectations.
\item Systems' maintainers should make it easier.
\end{list}
\end{center}
\end{slide}

\begin{slide}
\begin{center}
{\bf Acknowledgments}\\
\begin{list}{$\bullet$}{\listinit}
\item The NRL IPv6+IPsec team, past and present
\item Ronald Lee, Chris Telfer, Chris Winters, and I did the\\
recent porting work discussed.
\item The OS maintainers, esp. those who helped us get code
running on their systems.
\end{list}
\end{center}
\end{slide}

\end{document}
