aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEthan Jackson <ethan@nicira.com>2011-12-15 17:58:23 -0800
committerEthan Jackson <ethan@nicira.com>2012-01-10 14:30:15 -0800
commitc97664b30f65d3a087076cb33242ffe2cc52a814 (patch)
tree6037a862dc1e52c850ec03a91c0dd2f4d18689b2 /lib
parent65120a8a4ec658f4318ca3ac6159e27f584bca8e (diff)
packets: New packet_set_*() helper functions.
This commit pulls code used to modify L3 and L4 header fields from dp_netdev into the packet library. An additional user will be added in a future commit. Signed-off-by: Ethan Jackson <ethan@nicira.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/dpif-netdev.c120
-rw-r--r--lib/packets.c101
-rw-r--r--lib/packets.h4
3 files changed, 116 insertions, 109 deletions
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 4ef2e3b4..f1d49b69 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1053,109 +1053,6 @@ dp_netdev_set_dl(struct ofpbuf *packet, const struct ovs_key_ethernet *eth_key)
}
static void
-dp_netdev_set_ip_addr(struct ofpbuf *packet, ovs_be32 *addr, ovs_be32 new_addr)
-{
- struct ip_header *nh = packet->l3;
-
- if (nh->ip_proto == IPPROTO_TCP && packet->l7) {
- struct tcp_header *th = packet->l4;
- th->tcp_csum = recalc_csum32(th->tcp_csum, *addr, new_addr);
- } else if (nh->ip_proto == IPPROTO_UDP && packet->l7) {
- struct udp_header *uh = packet->l4;
- if (uh->udp_csum) {
- uh->udp_csum = recalc_csum32(uh->udp_csum, *addr, new_addr);
- if (!uh->udp_csum) {
- uh->udp_csum = htons(0xffff);
- }
- }
- }
- nh->ip_csum = recalc_csum32(nh->ip_csum, *addr, new_addr);
- *addr = new_addr;
-}
-
-static void
-dp_netdev_set_ip_tos(struct ip_header *nh, uint8_t new_tos)
-{
- uint8_t *field = &nh->ip_tos;
-
- nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field),
- htons((uint16_t) new_tos));
- *field = new_tos;
-}
-
-static void
-dp_netdev_set_ip_ttl(struct ip_header *nh, uint8_t new_ttl)
-{
- uint8_t *field = &nh->ip_ttl;
-
- nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),
- htons(new_ttl << 8));
- *field = new_ttl;
-}
-
-static void
-dp_netdev_set_ipv4(struct ofpbuf *packet, const struct ovs_key_ipv4 *ipv4_key)
-{
- struct ip_header *nh = packet->l3;
-
- if (nh->ip_src != ipv4_key->ipv4_src) {
- dp_netdev_set_ip_addr(packet, &nh->ip_src, ipv4_key->ipv4_src);
- }
- if (nh->ip_dst != ipv4_key->ipv4_dst) {
- dp_netdev_set_ip_addr(packet, &nh->ip_dst, ipv4_key->ipv4_dst);
- }
- if (nh->ip_tos != ipv4_key->ipv4_tos) {
- dp_netdev_set_ip_tos(nh, ipv4_key->ipv4_tos);
- }
- if (nh->ip_ttl != ipv4_key->ipv4_ttl) {
- dp_netdev_set_ip_ttl(nh, ipv4_key->ipv4_ttl);
- }
-}
-
-static void
-dp_netdev_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)
-{
- *csum = recalc_csum16(*csum, *port, new_port);
- *port = new_port;
-}
-
-static void
-dp_netdev_set_tcp_port(struct ofpbuf *packet, const struct ovs_key_tcp *tcp_key)
-{
- struct tcp_header *th = packet->l4;
-
- if (th->tcp_src != tcp_key->tcp_src) {
- dp_netdev_set_port(&th->tcp_src, tcp_key->tcp_src, &th->tcp_csum);
- }
- if (th->tcp_dst != tcp_key->tcp_dst) {
- dp_netdev_set_port(&th->tcp_dst, tcp_key->tcp_dst, &th->tcp_csum);
- }
-}
-
-static void
-dp_netdev_set_udp_port(struct ofpbuf *packet, const struct ovs_key_udp *udp_key)
-{
- struct udp_header *uh = packet->l4;
-
- if (uh->udp_csum) {
- if (uh->udp_src != udp_key->udp_src) {
- dp_netdev_set_port(&uh->udp_src, udp_key->udp_src, &uh->udp_csum);
- }
-
- if (uh->udp_dst != udp_key->udp_dst) {
- dp_netdev_set_port(&uh->udp_dst, udp_key->udp_dst, &uh->udp_csum);
- }
-
- if (!uh->udp_csum) {
- uh->udp_csum = htons(0xffff);
- }
- } else {
- uh->udp_src = udp_key->udp_src;
- uh->udp_dst = udp_key->udp_dst;
- }
-}
-
-static void
dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet,
uint16_t out_port)
{
@@ -1249,6 +1146,10 @@ static void
execute_set_action(struct ofpbuf *packet, const struct nlattr *a)
{
enum ovs_key_attr type = nl_attr_type(a);
+ const struct ovs_key_ipv4 *ipv4_key;
+ const struct ovs_key_tcp *tcp_key;
+ const struct ovs_key_udp *udp_key;
+
switch (type) {
case OVS_KEY_ATTR_TUN_ID:
case OVS_KEY_ATTR_PRIORITY:
@@ -1261,18 +1162,19 @@ execute_set_action(struct ofpbuf *packet, const struct nlattr *a)
break;
case OVS_KEY_ATTR_IPV4:
- dp_netdev_set_ipv4(packet,
- nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4)));
+ ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4));
+ packet_set_ipv4(packet, ipv4_key->ipv4_src, ipv4_key->ipv4_dst,
+ ipv4_key->ipv4_tos, ipv4_key->ipv4_ttl);
break;
case OVS_KEY_ATTR_TCP:
- dp_netdev_set_tcp_port(packet,
- nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp)));
+ tcp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp));
+ packet_set_tcp_port(packet, tcp_key->tcp_src, tcp_key->tcp_dst);
break;
case OVS_KEY_ATTR_UDP:
- dp_netdev_set_udp_port(packet,
- nl_attr_get_unspec(a, sizeof(struct ovs_key_udp)));
+ udp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp));
+ packet_set_udp_port(packet, udp_key->udp_src, udp_key->udp_dst);
break;
case OVS_KEY_ATTR_UNSPEC:
diff --git a/lib/packets.c b/lib/packets.c
index 25481742..eaf3e43f 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -22,6 +22,7 @@
#include <netinet/in.h>
#include <stdlib.h>
#include "byte-order.h"
+#include "csum.h"
#include "dynamic-string.h"
#include "ofpbuf.h"
@@ -377,3 +378,103 @@ snap_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
return payload;
}
+
+static void
+packet_set_ipv4_addr(struct ofpbuf *packet, ovs_be32 *addr, ovs_be32 new_addr)
+{
+ struct ip_header *nh = packet->l3;
+
+ if (nh->ip_proto == IPPROTO_TCP && packet->l7) {
+ struct tcp_header *th = packet->l4;
+
+ th->tcp_csum = recalc_csum32(th->tcp_csum, *addr, new_addr);
+ } else if (nh->ip_proto == IPPROTO_UDP && packet->l7) {
+ struct udp_header *uh = packet->l4;
+
+ if (uh->udp_csum) {
+ uh->udp_csum = recalc_csum32(uh->udp_csum, *addr, new_addr);
+ if (!uh->udp_csum) {
+ uh->udp_csum = htons(0xffff);
+ }
+ }
+ }
+ nh->ip_csum = recalc_csum32(nh->ip_csum, *addr, new_addr);
+ *addr = new_addr;
+}
+
+/* Modifies the IPv4 header fields of 'packet' to be consistent with 'src',
+ * 'dst', 'tos', and 'ttl'. Updates 'packet''s L4 checksums as appropriate.
+ * 'packet' must contain a valid IPv4 packet with correctly populated l[347]
+ * markers. */
+void
+packet_set_ipv4(struct ofpbuf *packet, ovs_be32 src, ovs_be32 dst,
+ uint8_t tos, uint8_t ttl)
+{
+ struct ip_header *nh = packet->l3;
+
+ if (nh->ip_src != src) {
+ packet_set_ipv4_addr(packet, &nh->ip_src, src);
+ }
+
+ if (nh->ip_dst != dst) {
+ packet_set_ipv4_addr(packet, &nh->ip_dst, dst);
+ }
+
+ if (nh->ip_tos != tos) {
+ uint8_t *field = &nh->ip_tos;
+
+ nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t) *field),
+ htons((uint16_t) tos));
+ *field = tos;
+ }
+
+ if (nh->ip_ttl != ttl) {
+ uint8_t *field = &nh->ip_ttl;
+
+ nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),
+ htons(ttl << 8));
+ *field = ttl;
+ }
+}
+
+static void
+packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)
+{
+ if (*port != new_port) {
+ *csum = recalc_csum16(*csum, *port, new_port);
+ *port = new_port;
+ }
+}
+
+/* Sets the TCP source and destination port ('src' and 'dst' respectively) of
+ * the TCP header contained in 'packet'. 'packet' must be a valid TCP packet
+ * with its l4 marker properly populated. */
+void
+packet_set_tcp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst)
+{
+ struct tcp_header *th = packet->l4;
+
+ packet_set_port(&th->tcp_src, src, &th->tcp_csum);
+ packet_set_port(&th->tcp_dst, dst, &th->tcp_csum);
+}
+
+/* Sets the UDP source and destination port ('src' and 'dst' respectively) of
+ * the UDP header contained in 'packet'. 'packet' must be a valid UDP packet
+ * with its l4 marker properly populated. */
+void
+packet_set_udp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst)
+{
+ struct udp_header *uh = packet->l4;
+
+ if (uh->udp_csum) {
+ packet_set_port(&uh->udp_src, src, &uh->udp_csum);
+ packet_set_port(&uh->udp_dst, dst, &uh->udp_csum);
+
+ if (!uh->udp_csum) {
+ uh->udp_csum = htons(0xffff);
+ }
+ } else {
+ uh->udp_src = src;
+ uh->udp_dst = dst;
+ }
+}
diff --git a/lib/packets.h b/lib/packets.h
index 16834a8b..78ccfe90 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -463,5 +463,9 @@ void *eth_compose(struct ofpbuf *, const uint8_t eth_dst[ETH_ADDR_LEN],
void *snap_compose(struct ofpbuf *, const uint8_t eth_dst[ETH_ADDR_LEN],
const uint8_t eth_src[ETH_ADDR_LEN],
unsigned int oui, uint16_t snap_type, size_t size);
+void packet_set_ipv4(struct ofpbuf *, ovs_be32 src, ovs_be32 dst, uint8_t tos,
+ uint8_t ttl);
+void packet_set_tcp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst);
+void packet_set_udp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst);
#endif /* packets.h */