From 695f4ed94cf2624aba15d05cd86a9a8b58640add Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Mon, 12 Aug 2019 12:13:59 +0200 Subject: [PATCH] ++doc --- doc/Background.tex | 10 ++- doc/Conclusion.tex | 71 ++++++++++++++- doc/Design.tex | 159 ++++++++++++++++++++++++++++----- doc/Introduction.tex | 5 +- doc/Makefile | 2 +- doc/Results.tex | 52 +++++------ doc/graphviz/netpfgadesign.dot | 36 ++++++++ doc/graphviz/netpfgadesign.png | Bin 0 -> 16580 bytes doc/graphviz/switchdesign.dot | 19 ++++ doc/graphviz/switchdesign.png | Bin 0 -> 9022 bytes doc/plan.org | 18 ++-- doc/refs/refs.bib | 26 ++++++ p4src/actions_nat64_generic.p4 | 2 +- 13 files changed, 330 insertions(+), 70 deletions(-) create mode 100644 doc/graphviz/netpfgadesign.dot create mode 100644 doc/graphviz/netpfgadesign.png create mode 100644 doc/graphviz/switchdesign.dot create mode 100644 doc/graphviz/switchdesign.png diff --git a/doc/Background.tex b/doc/Background.tex index c7f4a90..60c0c4a 100644 --- a/doc/Background.tex +++ b/doc/Background.tex @@ -103,6 +103,11 @@ the two protocols for this thesis are: \label{fig:ipv4header} \end{figure} % ---------------------------------------------------------------------- +\section{\label{background:arpndp}ARP and NDP - FIXME} +Required for finding host. +ARP who has +NDP similar -- add traces here +% ---------------------------------------------------------------------- \section{\label{background:transition}IPv6 Translation Mechanisms} While in this thesis the focus was in NAT64 as a translation mechanism, there are a variety of different approaches, some of which we would @@ -304,6 +309,5 @@ IPv6 only networks are in our opinion the best choice for long term deployments. The reasons for this are as follows: First of all hosts eventually will need to support IPv6 and secondly IPv6 hosts can address the whole 32 bit IPv4 Internet mapped in -a single /96 IPv6 network, whithout the need for address extension or -higher protocol dependent translations\footnote{Higher level protocols - like TCP, UDP, ICMP6/ICMP.} +a single /96 IPv6 network. IPv6 only networks also allow the operators +to focus on one IP stack. diff --git a/doc/Conclusion.tex b/doc/Conclusion.tex index 43cbd5b..109ea34 100644 --- a/doc/Conclusion.tex +++ b/doc/Conclusion.tex @@ -9,20 +9,89 @@ Sum up what you have done and recapitulate your key findings. \section{\label{conclusion:softwarenat64}Software based NAT64} +\section{\label{conclusion:general}General} +Many misleading + + \section{\label{conclusion:bmv2}BMV2} maybe remove \section{\label{conclusion:P4}P4} + +checksumming a frequent problem and helper + Many possibilities Protocol independent Easy architecture Limitations in +if in action limitations -\section{\label{conclusion:netpfga}NetFGPA} +Limits if in actions + +python2 only - unicode errors + +IPv6: NDP: not easy to parse, as unknown number of following fields + +No support for multiple LPM keys in a table, can be solved with +ternary matching. + +switch cannot be used in actions + +\begin{verbatim} +ipaddress.ip_network("2001:db8:61::/64") +IPv6Network(u'3230:3031:3a64:6238:3a36:313a:3a2f:3634/128') + +Fix: +from __future__ import unicode_literals + +\end{verbatim} + +The tooling around P4 is still fragile, encountered many bugs +in the development.\cite{schottelius:github1675} + +or missing features (\cite{schottelius:github745}, +\cite{theojepsen:_get}) + +Hitting expression bug + +\section{\label{conclusion:netpfga}NetFGPA - all HERE} personal note here + +long compile process +error prone compile process +many dependencies +lpm not supported! +Netpfga live, +Vivado +SDNET +xx k lines of supporting code + +no payload accessq + +Many workarounds + +Table size 63, table size 64, + +Table entries require arguments of all possible actions, not only used +one. + +Compile time hours + +Silent errors + +Unclear errors: broken board + +Due to the very fragile nature of the build framework from the +NetFPGA-Live repository, + +Renaming VARIABLES in the definition of + +Reproducibility: + + \section{\label{conclusion:realworld}Real world applications} Can be deployed using the netpfga. Or Barefoot or Arista. diff --git a/doc/Design.tex b/doc/Design.tex index f73be7c..30bca96 100644 --- a/doc/Design.tex +++ b/doc/Design.tex @@ -2,29 +2,148 @@ Description of the theory/software/hardware that you designed. %** Design.tex: How was the problem attacked, what was the design % the architecture +In this chapter we describe the architecture of our solution. -Maybe figures here? controller, - +% ---------------------------------------------------------------------- \section{\label{Design:General}General} -There are a variety of possible network layouts for realising -NAT64. In this thesis two different layouts where taken into account: -routed translation and transparent in network translation. - +The high level design can be seen in figure \ref{fig:switchdesign}: a +P4 capable switch is running our code to provide NAT64 +functionality. The P4 switch cannot manage its tables on it own and +needs support for this from a controller. If only static table entries +are required, the controller can also be omitted. However stateful +NAT64 requires the use of a control to create session entries in the +switch tables. +\begin{figure}[h] + \includegraphics[scale=0.5]{switchdesign} + \centering + \caption{General Design} + \label{fig:switchdesign} +\end{figure} +The P4 switch can use any protocol to communicate with controller, as +the connection to the controller is implemented as a separate ethernet +port. The design allows our solution to be used as a standard NAT64 +translation method or as an in network NAT64 translation (compare +figures \ref{fig:v6v4innetwork} and \ref{fig:v6v4standard}). The +controller is implemented in python, the NAT64 solution is implemented +in P4. +% ---------------------------------------------------------------------- \section{\label{Design:BMV2}BMV2} - - -\section{\label{Design:NetPFGA}NetFPGA} - -Netpfga live, -Vivado -SDNET -xx k lines of supporting code - -\section{todo} - +Development of the thesis took place on a software emulated switch +that is implemented using Open vSwitch \cite{openvswitch} +and the behavioral model +\cite{_implem_your_switc_target_with_bmv2}. The development followed +closely the general design shown in section +\ref{Design:General}. Within the software emulation checksums can be +computed with two different methods: +\begin{itemize} +\item Recalculating the checksum by inspecting headers and payload +\item Calculating the difference between the translated headers +\end{itemize} +The BMV2 model is rather sophisticated and provides many standard +features including checksumming over payload. This allows the BMV2 +model to operate as a full featured host, including advanced features +like responding to ICMP6 Neighbor discovery requests \cite{rfc4861} +that include payload checksums. +A typical code to create the checksum can be found in figure +\ref{fig:checksum}. +\begin{figure}[h] \begin{verbatim} -***** Verschiedene design Möglichkeiten -***** Proxy und co. -***** Generell vs. spefizisch +/* checksumming for icmp6_na_ns_option */ +update_checksum_with_payload(meta.chk_icmp6_na_ns == 1, + { + hdr.ipv6.src_addr, /* 128 */ + hdr.ipv6.dst_addr, /* 128 */ + meta.cast_length, /* 32 */ + 24w0, /* 24 0's */ + PROTO_ICMP6, /* 8 */ + hdr.icmp6.type, /* 8 */ + hdr.icmp6.code, /* 8 */ + + hdr.icmp6_na_ns.router, + hdr.icmp6_na_ns.solicitated, + hdr.icmp6_na_ns.override, + hdr.icmp6_na_ns.reserved, + hdr.icmp6_na_ns.target_addr, + + hdr.icmp6_option_link_layer_addr.type, + hdr.icmp6_option_link_layer_addr.ll_length, + hdr.icmp6_option_link_layer_addr.mac_addr + }, + hdr.icmp6.checksum, + HashAlgorithm.csum16 +); +\end{verbatim} + \centering + \caption{IPv4 Pseudo Header} + \label{fig:checksum} +\end{figure} + +% ---------------------------------------------------------------------- +\section{\label{Design:NetPFGA}NetFPGA} +While the P4-NetFPGA project \cite{netfpga:_p4_netpf_public_github} +allows compiling P4 to the NetPFGA, the design slightly varies. +In particular, the NetFPGA P4 compiler does not support reading +the payload. For this reason it also does not support +creating the checksum based on the payload. +To support checksum modifications in NAT64 on the NetFPGA, the +checksum was calculated on the netpfga using differences between +the IPv6 and IPv4 headers. Figure \ref{fig:checksumbydiff} shows an +excerpt of the code used for calculating checksums in the netpfga. +\begin{figure}[h] +\begin{verbatim} +action v4sum() { + bit<16> tmp = 0; + + tmp = tmp + (bit<16>) hdr.ipv4.src_addr[15:0]; // 16 bit + tmp = tmp + (bit<16>) hdr.ipv4.src_addr[31:16]; // 16 bit + tmp = tmp + (bit<16>) hdr.ipv4.dst_addr[15:0]; // 16 bit + tmp = tmp + (bit<16>) hdr.ipv4.dst_addr[31:16]; // 16 bit + + tmp = tmp + (bit<16>) hdr.ipv4.totalLen -20; // 16 bit + tmp = tmp + (bit<16>) hdr.ipv4.protocol; // 8 bit + + meta.v4sum = ~tmp; +} + +/* analogue code for v6sum skipped */ + +action delta_tcp_from_v6_to_v4() +{ + v6sum(); + v4sum(); + + bit<17> tmp = (bit<17>) hdr.tcp.checksum + (bit<17>) meta.v4sum; + if (tmp[16:16] == 1) { + tmp = tmp + 1; + tmp[16:16] = 0; + } + tmp = tmp + (bit<17>) (0xffff - meta.v6sum); + if (tmp[16:16] == 1) { + tmp = tmp + 1; + tmp[16:16] = 0; + } + + hdr.tcp.checksum = (bit<16>) tmp; +} \end{verbatim} + \centering + \caption{Calculating checksum based on header differences} + \label{fig:checksumbydiff} +\end{figure} +The checksums for IPv4, TCP, UDP and ICMP6 are all based on the +``Internet Checksum'' (\cite{rfc791}, \cite{rfc1071}). Its calculation +can be summarised as follows: +\begin{quote} + The checksum field is the 16-bit one's complement of the one's + complement sum of all 16-bit words in the header. For purposes of + computing the checksum, the value of the checksum field + is zero.\footnote{Quote from Wikipedia\cite{wikipedia:_ipv4}.}. +\end{quote} +As the calculation mainly depends on on (1-complement) sums, the +checksums after translating the protocol can be corrected by +subtracting the differences of the relevant fields. It is notable that +not the full headers are used, but the pseudo headers (compare figures +\ref{fig:ipv6pseudoheader} and \ref{fig:ipv4pseudoheader}). +To compensate the carry bit, our code uses 17 bit integers for +correcting the carry. diff --git a/doc/Introduction.tex b/doc/Introduction.tex index 82fed05..39997d7 100644 --- a/doc/Introduction.tex +++ b/doc/Introduction.tex @@ -80,7 +80,6 @@ approach and \ref{fig:v6v4innetwork} shows our solution. \caption{In Network NAT64 translation} \label{fig:v6v4innetwork} \end{figure} - \begin{figure}[h] \includegraphics[scale=0.7]{v6-v4-standard} \centering @@ -89,9 +88,9 @@ approach and \ref{fig:v6v4innetwork} shows our solution. \end{figure} Currently network operators have to focus on two network stacks when designing networks: IPv6 and IPv4. While in a small scale setup this -might not introduce significant complexity, however figure +might not introduce significant complexity, figure \ref{fig:v6v4mixed} shows how the complexity quickly grows -quickly with the number of nodes. +with the number of hosts. \begin{figure}[h] \includegraphics[scale=0.4]{v6-v4-mixed} \centering diff --git a/doc/Makefile b/doc/Makefile index 39364ee..d4582d6 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -9,7 +9,7 @@ all: all-graphviz pdflatex $(FILE) clean: - rm -f *.dvi *.log *.aux *.bbl *.blg *.toc *.lof *.lot *.cb *.~ + rm -f *.dvi *.log *.aux *.bbl *.blg *.toc *.lof *.lot *.cb *.~ *.ilg *.nlo *.nls *.out *.glo all-graphviz: for dot in graphviz/*.dot; do make $${dot%%.dot}.png; done diff --git a/doc/Results.tex b/doc/Results.tex index a654298..5c39d6a 100644 --- a/doc/Results.tex +++ b/doc/Results.tex @@ -2,53 +2,41 @@ %** Results.tex: What were the results achieved including an evaluation % -The results from your evaluations. +\section{\label{results:general}General} +Parser for all protocols (udp,tcp,icmp,icmp6) + +BMV2: more feature rich, but software only solution +NetFPGA: capabale of line speed Nat64, focused port on nat64 -\begin{itemize} -\item Solution in P4/BMV2 -\item Solution in P4/NetFPGA -\end{itemize} \section{\label{Results:BMV2}BMV2} + +Responds to icmp, icmp6 ndp arp test framework openvswitch +Fully functional host +Can compute checksums on its own. + +\section{\label{results:tayga}Tayga} + +3gbit + +\section{\label{results:jool}Jool} \section{\label{Results:NetPFGA}NetFPGA} General result: limited NAT64 is working, however -\subsection{\label{Results:NetPFGA:challenge-checksum}No Payload - checksumming} + No Payload + checksumming - requires controller -Hash funktion in Arbeit + Hash funktion in Arbeit -\subsection{\label{Results:NetPFGA:challenges}Other Challenges} -Many workarounds - -Table size 63, table size 64, - -Table entries require arguments of all possible actions, not only used -one. - -Compile time hours - -Silent errors - -Unclear errors: broken board - -Due to the very fragile nature of the build framework from the -NetFPGA-Live repository, - -Renaming VARIABLES in the definition of - -Reproducibility: - -\section{\label{Results:P4}P4} - -Limits if in actions + No NDP, no ARP - focused on key factors of NAT64 translation, + other features can be supported by controller \section{\label{results:softwarenat64}NAT64 in Software} Tayga, Jool diff --git a/doc/graphviz/netpfgadesign.dot b/doc/graphviz/netpfgadesign.dot new file mode 100644 index 0000000..e3de9bb --- /dev/null +++ b/doc/graphviz/netpfgadesign.dot @@ -0,0 +1,36 @@ +graph G { + node [ shape="box"]; + rankdir="LR"; + + x520_1 [ label="X520: IPv4" ]; + x520_2 [ label="X520: IPv6" ]; + x520_nsg [ label="X520: Controller" ]; + + netpfga1 [ label="NetFPGA Port 1" ]; + netpfga2 [ label="NetFPGA Port 2" ]; + netpfga3 [ label="NetFPGA Port 3" ]; + + + + subgraph cluster_esprimo { + label="Load generator"; + + x520_1; + x520_2; + } + + subgraph cluster_nsg { + label="NetFPGA Host"; + + netpfga1; + netpfga2; + + netpfga3--x520_nsg; + } + + x520_1--netpfga1; + x520_2--netpfga2; + + + +} diff --git a/doc/graphviz/netpfgadesign.png b/doc/graphviz/netpfgadesign.png new file mode 100644 index 0000000000000000000000000000000000000000..152bdd0ceeac6d2139a30dd05ea9b1d0db8d93d0 GIT binary patch literal 16580 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 ca_j|gYFPW(o~eHh55ypp?`WX% to bit<32> in checksum causes incorrect json to be generated}, + howpublished = {\url{https://github.com/p4lang/p4c/issues/1765}}} + +@Misc{schottelius:github745, + author = {Nico Schottelius}, + title = {Add access to table keys}, + howpublished = {\url{https://github.com/p4lang/p4-spec/issues/745}}} + +@Misc{theojepsen:_get, + author = {theojepsen}, + title = {Get size of header}, + howpublished = {\url{https://github.com/p4lang/p4-spec/issues/660}}} diff --git a/p4src/actions_nat64_generic.p4 b/p4src/actions_nat64_generic.p4 index 7c0dc49..3908520 100644 --- a/p4src/actions_nat64_generic.p4 +++ b/p4src/actions_nat64_generic.p4 @@ -1,4 +1,4 @@ -#ifndef NICO_NAT64_GENERIC +xf#ifndef NICO_NAT64_GENERIC #define NICO_NAT64_GENERIC #include "actions_egress.p4"