From 7470a213077d68c7108639d7c88e6129d31a40f8 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 14 Jul 2008 13:54:38 -0700 Subject: [PATCH] packets: Move IP checksum functionality into new csum.c, csum.h. --- include/Makefile.am | 1 + include/csum.h | 48 +++++++++++++++++++ lib/Makefile.am | 1 + lib/csum.c | 114 ++++++++++++++++++++++++++++++++++++++++++++ switch/datapath.c | 29 +---------- 5 files changed, 165 insertions(+), 28 deletions(-) create mode 100644 include/csum.h create mode 100644 lib/csum.c diff --git a/include/Makefile.am b/include/Makefile.am index 12d1e0b2..e773ba0a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,6 +2,7 @@ noinst_HEADERS = \ buffer.h \ command-line.h \ compiler.h \ + csum.h \ daemon.h \ dynamic-string.h \ dpif.h \ diff --git a/include/csum.h b/include/csum.h new file mode 100644 index 00000000..d9253e00 --- /dev/null +++ b/include/csum.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#ifndef CSUM_H +#define CSUM_H 1 + +#include +#include + +uint16_t csum(const void *, size_t); +uint32_t csum_add16(uint32_t partial, uint16_t); +uint32_t csum_add32(uint32_t partial, uint32_t); +uint32_t csum_continue(uint32_t partial, const void *, size_t); +uint16_t csum_finish(uint32_t partial); +uint16_t recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16); +uint16_t recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32); + +#endif /* csum.h */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 719f827b..cdc87ca4 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -5,6 +5,7 @@ noinst_LTLIBRARIES = libopenflow.la libopenflow_la_SOURCES = \ buffer.c \ command-line.c \ + csum.c \ daemon.c \ dynamic-string.c \ fatal-signal.c \ diff --git a/lib/csum.c b/lib/csum.c new file mode 100644 index 00000000..6e9b06b0 --- /dev/null +++ b/lib/csum.c @@ -0,0 +1,114 @@ +/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#include "csum.h" + +/* Returns the IP checksum of the 'n' bytes in 'data'. */ +uint16_t +csum(const void *data, size_t n) +{ + return csum_finish(csum_continue(0, data, n)); +} + +/* Adds the 16 bits in 'new' to the partial IP checksum 'partial' and returns + * the updated checksum. (To start a new checksum, pass 0 for 'partial'. To + * obtain the finished checksum, pass the return value to csum_finish().) */ +uint32_t +csum_add16(uint32_t partial, uint16_t new) +{ + return partial + new; +} + +/* Adds the 32 bits in 'new' to the partial IP checksum 'partial' and returns + * the updated checksum. (To start a new checksum, pass 0 for 'partial'. To + * obtain the finished checksum, pass the return value to csum_finish().) */ +uint32_t +csum_add32(uint32_t partial, uint32_t new) +{ + return partial + (new >> 16) + (new & 0xffff); +} + + +/* Adds the 'n' bytes in 'data' to the partial IP checksum 'partial' and + * returns the updated checksum. (To start a new checksum, pass 0 for + * 'partial'. To obtain the finished checksum, pass the return value to + * csum_finish().) */ +uint32_t +csum_continue(uint32_t partial, const void *data_, size_t n) +{ + const uint16_t *data = data_; + + for (; n > 1; n -= 2) { + partial = csum_add16(partial, *data++); + } + if (n) { + partial += *(uint8_t *) data; + } + return partial; +} + +/* Returns the IP checksum corresponding to 'partial', which is a value updated + * by some combination of csum_add16(), csum_add32(), and csum_continue(). */ +uint16_t +csum_finish(uint32_t partial) +{ + return ~((partial & 0xffff) + (partial >> 16)); +} + +/* Returns the new checksum for a packet in which the checksum field previously + * contained 'old_csum' and in which a field that contained 'old_u16' was + * changed to contain 'new_u16'. */ +uint16_t +recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16) +{ + /* Ones-complement arithmetic is endian-independent, so this code does not + * use htons() or ntohs(). + * + * See RFC 1624 for formula and explanation. */ + uint16_t hc_complement = ~old_csum; + uint16_t m_complement = ~old_u16; + uint16_t m_prime = new_u16; + uint32_t sum = hc_complement + m_complement + m_prime; + uint16_t hc_prime_complement = sum + (sum >> 16); + return ~hc_prime_complement; +} + +/* Returns the new checksum for a packet in which the checksum field previously + * contained 'old_csum' and in which a field that contained 'old_u32' was + * changed to contain 'new_u32'. */ +uint16_t +recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32) +{ + return recalc_csum16(recalc_csum16(old_csum, old_u32, new_u32), + old_u32 >> 16, new_u32 >> 16); +} diff --git a/switch/datapath.c b/switch/datapath.c index 3d639ff2..a196bead 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -40,6 +40,7 @@ #include #include "buffer.h" #include "chain.h" +#include "csum.h" #include "flow.h" #include "netdev.h" #include "packets.h" @@ -858,34 +859,6 @@ execute_actions(struct datapath *dp, struct buffer *buffer, buffer_delete(buffer); } -/* Returns the new checksum for a packet in which the checksum field previously - * contained 'old_csum' and in which a field that contained 'old_u16' was - * changed to contain 'new_u16'. */ -static uint16_t -recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16) -{ - /* Ones-complement arithmetic is endian-independent, so this code does not - * use htons() or ntohs(). - * - * See RFC 1624 for formula and explanation. */ - uint16_t hc_complement = ~old_csum; - uint16_t m_complement = ~old_u16; - uint16_t m_prime = new_u16; - uint32_t sum = hc_complement + m_complement + m_prime; - uint16_t hc_prime_complement = sum + (sum >> 16); - return ~hc_prime_complement; -} - -/* Returns the new checksum for a packet in which the checksum field previously - * contained 'old_csum' and in which a field that contained 'old_u32' was - * changed to contain 'new_u32'. */ -static uint16_t -recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32) -{ - return recalc_csum16(recalc_csum16(old_csum, old_u32, new_u32), - old_u32 >> 16, new_u32 >> 16); -} - static void modify_nh(struct buffer *buffer, uint16_t eth_proto, uint8_t nw_proto, const struct ofp_action *a) { -- 2.30.2