@@ -307,8 +307,6 @@ lib_libopenvswitch_la_SOURCES = \
lib/ovsdb-types.h \
lib/ox-stat.c \
lib/ox-stat.h \
- lib/packets.c \
- lib/packets.h \
lib/pcap-file.c \
lib/pcap-file.h \
lib/perf-counter.h \
@@ -38,7 +38,6 @@
#include "openvswitch/ofpbuf.h"
#include "ovs-thread.h"
#include "openvswitch/types.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "random.h"
#include "seq.h"
@@ -21,7 +21,7 @@
#include <stdbool.h>
#include <inttypes.h>
-#include "packets.h"
+#include "net-proto.h"
struct bfd;
struct dpif_flow_stats;
@@ -31,7 +31,6 @@
#include "openvswitch/hmap.h"
#include "netdev.h"
#include "ovs-atomic.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "random.h"
#include "seq.h"
@@ -20,7 +20,6 @@
#include "openvswitch/hmap.h"
#include "openvswitch/types.h"
-#include "packets.h"
struct flow;
struct dp_packet;
@@ -24,7 +24,6 @@
#include "openvswitch/dynamic-string.h"
#include "net-proto.h"
#include "odp-util.h"
-#include "packets.h"
#include "util.h"
struct trie_ctx;
@@ -28,7 +28,6 @@
#include "openvswitch/hmap.h"
#include "openvswitch/list.h"
#include "openvswitch/types.h"
-#include "packets.h"
#include "rculist.h"
#include "unaligned.h"
#include "dp-packet.h"
@@ -29,7 +29,6 @@
#include "openvswitch/types.h"
#include "ovs-atomic.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "hindex.h"
/* Userspace connection tracker
@@ -62,6 +61,7 @@
*/
struct dp_packet_batch;
+struct dp_packet;
struct conntrack;
@@ -20,6 +20,7 @@
#include <errno.h>
#include "ct-dpif.h"
+#include "openvswitch/dynamic-string.h"
#include "openvswitch/ofp-ct.h"
#include "openvswitch/ofp-parse.h"
#include "openvswitch/vlog.h"
@@ -17,8 +17,8 @@
#ifndef CT_DPIF_H
#define CT_DPIF_H
+#include "openvswitch/list.h"
#include "openvswitch/types.h"
-#include "packets.h"
struct ofp_ct_match;
@@ -228,6 +228,7 @@ enum {
CT_STATS_MAX,
};
+struct ds;
struct dpif;
struct dpif_ipf_status;
struct ipf_dump_ctx;
@@ -18,7 +18,6 @@
#define DHCP_H 1
#include <stdint.h>
-#include "packets.h"
#include "util.h"
/* Ports used by DHCP. */
@@ -15,13 +15,20 @@
*/
#include <config.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
#include <stdlib.h>
#include <string.h>
+#include "crc32c.h"
#include "dp-packet.h"
+#include "dp-packet-gso.h"
#include "netdev-afxdp.h"
#include "netdev-dpdk.h"
#include "netdev-provider.h"
+#include "net-proto.h"
#include "openvswitch/dynamic-string.h"
#include "util.h"
@@ -646,3 +653,1404 @@ dp_packet_ol_send_prepare(struct dp_packet *p, uint64_t flags)
}
}
}
+
+
+
+struct in6_addr
+flow_tnl_dst(const struct flow_tnl *tnl)
+{
+ return tnl->ip_dst ? in6_addr_mapped_ipv4(tnl->ip_dst) : tnl->ipv6_dst;
+}
+
+struct in6_addr
+flow_tnl_src(const struct flow_tnl *tnl)
+{
+ return tnl->ip_src ? in6_addr_mapped_ipv4(tnl->ip_src) : tnl->ipv6_src;
+}
+
+/* Fills 'b' with a Reverse ARP packet with Ethernet source address 'eth_src'.
+ * This function is used by Open vSwitch to compose packets in cases where
+ * context is important but content doesn't (or shouldn't) matter.
+ *
+ * The returned packet has enough headroom to insert an 802.1Q VLAN header if
+ * desired. */
+void
+compose_rarp(struct dp_packet *b, const struct eth_addr eth_src)
+{
+ struct eth_header *eth;
+ struct arp_eth_header *arp;
+
+ dp_packet_clear(b);
+ dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN
+ + ARP_ETH_HEADER_LEN);
+ dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
+ eth = dp_packet_put_uninit(b, sizeof *eth);
+ eth->eth_dst = eth_addr_broadcast;
+ eth->eth_src = eth_src;
+ eth->eth_type = htons(ETH_TYPE_RARP);
+
+ arp = dp_packet_put_uninit(b, sizeof *arp);
+ arp->ar_hrd = htons(ARP_HRD_ETHERNET);
+ arp->ar_pro = htons(ARP_PRO_IP);
+ arp->ar_hln = sizeof arp->ar_sha;
+ arp->ar_pln = sizeof arp->ar_spa;
+ arp->ar_op = htons(ARP_OP_RARP);
+ arp->ar_sha = eth_src;
+ put_16aligned_be32(&arp->ar_spa, htonl(0));
+ arp->ar_tha = eth_src;
+ put_16aligned_be32(&arp->ar_tpa, htonl(0));
+
+ dp_packet_set_l3(b, arp);
+ b->packet_type = htonl(PT_ETH);
+}
+
+/* Insert VLAN header according to given TCI. Packet passed must be Ethernet
+ * packet. Ignores the CFI bit of 'tci' using 0 instead.
+ *
+ * Also adjusts the layer offsets accordingly. */
+void
+eth_push_vlan(struct dp_packet *packet, ovs_be16 tpid, ovs_be16 tci)
+{
+ struct vlan_eth_header *veh;
+
+ /* Insert new 802.1Q header. */
+ veh = dp_packet_resize_l2(packet, VLAN_HEADER_LEN);
+ /* GCC cannot determine the buffer size through dp_packet_resize_l2 when
+ * both functions are in the same translation unit, causing a false
+ * positive around memmove. An alternative to this would be to disable
+ * inlining the dp_packet_resize_l2, but that seems excessive in this
+ * case. */
+#if __GNUC__ && !__clang__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+ /* Also, newer versions of GCC include a stringop overread check */
+#if __GNUC__ > 11
+#pragma GCC diagnostic ignored "-Wstringop-overread"
+#endif
+#endif
+ memmove(veh, (char *)veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN);
+#if __GNUC__ && !__clang__
+#pragma GCC diagnostic pop
+#endif
+ veh->veth_type = tpid;
+ veh->veth_tci = tci & htons(~VLAN_CFI);
+}
+
+/* Removes outermost VLAN header (if any is present) from 'packet'.
+ *
+ * 'packet->l2_5' should initially point to 'packet''s outer-most VLAN header
+ * or may be NULL if there are no VLAN headers. */
+void
+eth_pop_vlan(struct dp_packet *packet)
+{
+ struct vlan_eth_header *veh = dp_packet_eth(packet);
+
+ if (veh && dp_packet_size(packet) >= sizeof *veh
+ && eth_type_vlan(veh->veth_type)) {
+
+ memmove((char *)veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN);
+ dp_packet_resize_l2(packet, -VLAN_HEADER_LEN);
+ }
+}
+
+/* Push Ethernet header onto 'packet' assuming it is layer 3 */
+void
+push_eth(struct dp_packet *packet, const struct eth_addr *dst,
+ const struct eth_addr *src)
+{
+ struct eth_header *eh;
+
+ ovs_assert(!dp_packet_is_eth(packet));
+ eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);
+ eh->eth_dst = *dst;
+ eh->eth_src = *src;
+ eh->eth_type = pt_ns_type_be(packet->packet_type);
+ packet->packet_type = htonl(PT_ETH);
+}
+
+/* Removes Ethernet header, including VLAN header, from 'packet'.
+ *
+ * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */
+void
+pop_eth(struct dp_packet *packet)
+{
+ char *l2_5 = dp_packet_l2_5(packet);
+ char *l3 = dp_packet_l3(packet);
+ ovs_be16 ethertype;
+ int increment;
+
+ ovs_assert(dp_packet_is_eth(packet));
+ ovs_assert(l3 != NULL);
+
+ if (l2_5) {
+ increment = packet->l2_5_ofs;
+ ethertype = *(ALIGNED_CAST(ovs_be16 *, (l2_5 - 2)));
+ } else {
+ increment = packet->l3_ofs;
+ ethertype = *(ALIGNED_CAST(ovs_be16 *, (l3 - 2)));
+ }
+
+ dp_packet_resize_l2(packet, -increment);
+ packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, ntohs(ethertype));
+}
+
+/* Set ethertype of the packet. */
+static void
+set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)
+{
+ struct eth_header *eh = dp_packet_eth(packet);
+
+ if (!eh) {
+ return;
+ }
+
+ if (eth_type_vlan(eh->eth_type)) {
+ ovs_be16 *p;
+ char *l2_5 = dp_packet_l2_5(packet);
+
+ p = ALIGNED_CAST(ovs_be16 *,
+ (l2_5 ? l2_5 : (char *)dp_packet_l3(packet)) - 2);
+ *p = eth_type;
+ } else {
+ eh->eth_type = eth_type;
+ }
+}
+
+static bool is_mpls(struct dp_packet *packet)
+{
+ return packet->l2_5_ofs != UINT16_MAX;
+}
+
+/* Set MPLS label stack entry to outermost MPLS header.*/
+void
+set_mpls_lse(struct dp_packet *packet, ovs_be32 mpls_lse)
+{
+ /* Packet type should be MPLS to set label stack entry. */
+ if (is_mpls(packet)) {
+ struct mpls_hdr *mh = dp_packet_l2_5(packet);
+
+ /* Update mpls label stack entry. */
+ put_16aligned_be32(&mh->mpls_lse, mpls_lse);
+ }
+}
+
+/* Push MPLS label stack entry 'lse' onto 'packet' as the outermost MPLS
+ * header. If 'packet' does not already have any MPLS labels, then its
+ * Ethertype is changed to 'ethtype' (which must be an MPLS Ethertype). */
+void
+push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse)
+{
+ char * header;
+ size_t len;
+
+ if (!eth_type_mpls(ethtype)) {
+ return;
+ }
+
+ if (!is_mpls(packet)) {
+ /* Set MPLS label stack offset. */
+ packet->l2_5_ofs = packet->l3_ofs;
+ }
+
+ set_ethertype(packet, ethtype);
+
+ /* Push new MPLS shim header onto packet. */
+ len = packet->l2_5_ofs;
+ header = dp_packet_resize_l2_5(packet, MPLS_HLEN);
+ memmove(header, header + MPLS_HLEN, len);
+ memcpy(header + len, &lse, sizeof lse);
+
+ pkt_metadata_init_conn(&packet->md);
+}
+
+void
+add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,
+ bool l3_encap)
+{
+ if (!eth_type_mpls(ethtype)) {
+ return;
+ }
+
+ if (!l3_encap) {
+ struct mpls_hdr *header = dp_packet_resize_l2(packet, MPLS_HLEN);
+
+ put_16aligned_be32(&header->mpls_lse, lse);
+ packet->l2_5_ofs = 0;
+ packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,
+ ntohs(ethtype));
+ } else {
+ size_t len;
+ char *header;
+
+ if (!is_mpls(packet)) {
+ /* Set MPLS label stack offset. */
+ packet->l2_5_ofs = packet->l3_ofs;
+ }
+ set_ethertype(packet, ethtype);
+
+ /* Push new MPLS shim header onto packet. */
+ len = packet->l2_5_ofs;
+ header = dp_packet_resize_l2_5(packet, MPLS_HLEN);
+ memmove(header, header + MPLS_HLEN, len);
+ memcpy(header + len, &lse, sizeof lse);
+ }
+ pkt_metadata_init_conn(&packet->md);
+}
+
+/* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry.
+ * If the label that was removed was the only MPLS label, changes 'packet''s
+ * Ethertype to 'ethtype' (which ordinarily should not be an MPLS
+ * Ethertype). */
+void
+pop_mpls(struct dp_packet *packet, ovs_be16 ethtype)
+{
+ if (is_mpls(packet)) {
+ struct mpls_hdr *mh = dp_packet_l2_5(packet);
+ size_t len = packet->l2_5_ofs;
+
+ set_ethertype(packet, ethtype);
+ if (get_16aligned_be32(&mh->mpls_lse) & htonl(MPLS_BOS_MASK)) {
+ dp_packet_set_l2_5(packet, NULL);
+ }
+ /* Shift the l2 header forward. */
+ memmove((char*)dp_packet_data(packet) + MPLS_HLEN, dp_packet_data(packet), len);
+ dp_packet_resize_l2_5(packet, -MPLS_HLEN);
+
+ /* Invalidate offload flags as they are not valid after
+ * decapsulation of MPLS header. */
+ dp_packet_reset_offload(packet);
+
+ /* packet_type must be reset for the MPLS packets with no l2 header */
+ if (!len) {
+ if (ethtype == htons(ETH_TYPE_TEB)) {
+ /* The inner packet must be classified as ethernet if the
+ * ethtype is ETH_TYPE_TEB. */
+ packet->packet_type = htonl(PT_ETH);
+ } else {
+ packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,
+ ntohs(ethtype));
+ }
+ }
+ }
+}
+
+void
+push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src)
+{
+ struct nsh_hdr *nsh;
+ size_t length = nsh_hdr_len(nsh_hdr_src);
+ uint8_t next_proto;
+
+ switch (ntohl(packet->packet_type)) {
+ case PT_ETH:
+ next_proto = NSH_P_ETHERNET;
+ break;
+ case PT_IPV4:
+ next_proto = NSH_P_IPV4;
+ break;
+ case PT_IPV6:
+ next_proto = NSH_P_IPV6;
+ break;
+ case PT_NSH:
+ next_proto = NSH_P_NSH;
+ break;
+ default:
+ OVS_NOT_REACHED();
+ }
+
+ nsh = (struct nsh_hdr *) dp_packet_resize_l2(packet, length);
+ memcpy(nsh, nsh_hdr_src, length);
+ nsh->next_proto = next_proto;
+ packet->packet_type = htonl(PT_NSH);
+ dp_packet_reset_offsets(packet);
+ packet->l3_ofs = 0;
+}
+
+bool
+pop_nsh(struct dp_packet *packet)
+{
+ struct nsh_hdr *nsh = (struct nsh_hdr *) dp_packet_l3(packet);
+ size_t length;
+ uint32_t next_pt;
+
+ if (packet->packet_type == htonl(PT_NSH) && nsh) {
+ switch (nsh->next_proto) {
+ case NSH_P_ETHERNET:
+ next_pt = PT_ETH;
+ break;
+ case NSH_P_IPV4:
+ next_pt = PT_IPV4;
+ break;
+ case NSH_P_IPV6:
+ next_pt = PT_IPV6;
+ break;
+ case NSH_P_NSH:
+ next_pt = PT_NSH;
+ break;
+ default:
+ /* Unknown inner packet type. Drop packet. */
+ return false;
+ }
+
+ length = nsh_hdr_len(nsh);
+ dp_packet_reset_packet(packet, length);
+ packet->packet_type = htonl(next_pt);
+ /* Packet must be recirculated for further processing. */
+ }
+ return true;
+}
+
+/* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'. The
+ * caller must free '*packetp'. On success, returns NULL. On failure, returns
+ * an error message and stores NULL in '*packetp'.
+ *
+ * Aligns the L3 header of '*packetp' on a 32-bit boundary. */
+const char *
+eth_from_hex(const char *hex, struct dp_packet **packetp)
+{
+ struct dp_packet *packet;
+
+ /* Use 2 bytes of headroom to 32-bit align the L3 header. */
+ packet = *packetp = dp_packet_new_with_headroom(strlen(hex) / 2, 2);
+
+ if (dp_packet_put_hex(packet, hex, NULL)[0] != '\0') {
+ dp_packet_delete(packet);
+ *packetp = NULL;
+ return "Trailing garbage in packet data";
+ }
+
+ if (dp_packet_size(packet) < ETH_HEADER_LEN) {
+ dp_packet_delete(packet);
+ *packetp = NULL;
+ return "Packet data too short for Ethernet";
+ }
+
+ return NULL;
+}
+
+/* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',
+ * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated
+ * in 'b' and returned. This payload may be populated with appropriate
+ * information by the caller. Sets 'b''s 'frame' pointer and 'l3' offset to
+ * the Ethernet header and payload respectively. Aligns b->l3 on a 32-bit
+ * boundary.
+ *
+ * The returned packet has enough headroom to insert an 802.1Q VLAN header if
+ * desired. */
+void *
+eth_compose(struct dp_packet *b, const struct eth_addr eth_dst,
+ const struct eth_addr eth_src, uint16_t eth_type,
+ size_t size)
+{
+ void *data;
+ struct eth_header *eth;
+
+
+ dp_packet_clear(b);
+
+ /* The magic 2 here ensures that the L3 header (when it is added later)
+ * will be 32-bit aligned. */
+ dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size);
+ dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
+ eth = dp_packet_put_uninit(b, ETH_HEADER_LEN);
+ data = dp_packet_put_zeros(b, size);
+
+ eth->eth_dst = eth_dst;
+ eth->eth_src = eth_src;
+ eth->eth_type = htons(eth_type);
+
+ b->packet_type = htonl(PT_ETH);
+ dp_packet_set_l3(b, data);
+
+ return data;
+}
+
+void
+packet_set_ipv4_addr(struct dp_packet *packet,
+ ovs_16aligned_be32 *addr, ovs_be32 new_addr)
+{
+ struct ip_header *nh = dp_packet_l3(packet);
+ ovs_be32 old_addr = get_16aligned_be32(addr);
+ size_t l4_size = dp_packet_l4_size(packet);
+
+ pkt_metadata_init_conn(&packet->md);
+
+ if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
+ if (dp_packet_l4_checksum_valid(packet)) {
+ dp_packet_l4_checksum_set_partial(packet);
+ } else {
+ struct tcp_header *th = dp_packet_l4(packet);
+ th->tcp_csum = recalc_csum32(th->tcp_csum, old_addr, new_addr);
+ }
+ } else if (nh->ip_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN ) {
+ if (dp_packet_l4_checksum_valid(packet)) {
+ dp_packet_l4_checksum_set_partial(packet);
+ } else {
+ struct udp_header *uh = dp_packet_l4(packet);
+ if (uh->udp_csum) {
+ uh->udp_csum = recalc_csum32(uh->udp_csum, old_addr, new_addr);
+ if (!uh->udp_csum) {
+ uh->udp_csum = htons(0xffff);
+ }
+ }
+ }
+ }
+
+ if (dp_packet_ip_checksum_valid(packet)) {
+ dp_packet_ip_checksum_set_partial(packet);
+ } else {
+ nh->ip_csum = recalc_csum32(nh->ip_csum, old_addr, new_addr);
+ }
+ put_16aligned_be32(addr, new_addr);
+}
+
+/* Returns true, if packet contains at least one routing header where
+ * segements_left > 0.
+ *
+ * This function assumes that L3 and L4 offsets are set in the packet. */
+bool
+packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr, bool *first_frag)
+{
+ const struct ovs_16aligned_ip6_hdr *nh;
+ size_t len;
+ size_t remaining;
+ uint8_t *data = dp_packet_l3(packet);
+
+ remaining = packet->l4_ofs - packet->l3_ofs;
+ if (remaining < sizeof *nh) {
+ return false;
+ }
+ nh = ALIGNED_CAST(struct ovs_16aligned_ip6_hdr *, data);
+ data += sizeof *nh;
+ remaining -= sizeof *nh;
+ *nexthdr = nh->ip6_nxt;
+
+ while (1) {
+ if ((*nexthdr != IPPROTO_HOPOPTS)
+ && (*nexthdr != IPPROTO_ROUTING)
+ && (*nexthdr != IPPROTO_DSTOPTS)
+ && (*nexthdr != IPPROTO_AH)
+ && (*nexthdr != IPPROTO_FRAGMENT)) {
+ /* It's either a terminal header (e.g., TCP, UDP) or one we
+ * don't understand. In either case, we're done with the
+ * packet, so use it to fill in 'nw_proto'. */
+ break;
+ }
+
+ /* We only verify that at least 8 bytes of the next header are
+ * available, but many of these headers are longer. Ensure that
+ * accesses within the extension header are within those first 8
+ * bytes. All extension headers are required to be at least 8
+ * bytes. */
+ if (remaining < 8) {
+ return false;
+ }
+
+ if (*nexthdr == IPPROTO_AH) {
+ /* A standard AH definition isn't available, but the fields
+ * we care about are in the same location as the generic
+ * option header--only the header length is calculated
+ * differently. */
+ const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;
+
+ *nexthdr = ext_hdr->ip6e_nxt;
+ len = (ext_hdr->ip6e_len + 2) * 4;
+ } else if (*nexthdr == IPPROTO_FRAGMENT) {
+ const struct ovs_16aligned_ip6_frag *frag_hdr
+ = ALIGNED_CAST(struct ovs_16aligned_ip6_frag *, data);
+
+ *first_frag = !(frag_hdr->ip6f_offlg & IP6F_OFF_MASK) &&
+ (frag_hdr->ip6f_offlg & IP6F_MORE_FRAG);
+ *nexthdr = frag_hdr->ip6f_nxt;
+ len = sizeof *frag_hdr;
+ } else if (*nexthdr == IPPROTO_ROUTING) {
+ const struct ip6_rthdr *rh = (struct ip6_rthdr *)data;
+
+ if (rh->ip6r_segleft > 0) {
+ return true;
+ }
+
+ *nexthdr = rh->ip6r_nxt;
+ len = (rh->ip6r_len + 1) * 8;
+ } else {
+ const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;
+
+ *nexthdr = ext_hdr->ip6e_nxt;
+ len = (ext_hdr->ip6e_len + 1) * 8;
+ }
+
+ if (remaining < len) {
+ return false;
+ }
+ remaining -= len;
+ data += len;
+ }
+
+ return false;
+}
+
+static void
+packet_update_csum128(struct dp_packet *packet, uint8_t proto,
+ ovs_16aligned_be32 addr[4],
+ const struct in6_addr *new_addr)
+{
+ size_t l4_size = dp_packet_l4_size(packet);
+
+ if (proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
+ if (dp_packet_l4_checksum_valid(packet)) {
+ dp_packet_l4_checksum_set_partial(packet);
+ } else {
+ struct tcp_header *th = dp_packet_l4(packet);
+
+ th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr);
+ }
+ } else if (proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
+ if (dp_packet_l4_checksum_valid(packet)) {
+ dp_packet_l4_checksum_set_partial(packet);
+ } else {
+ struct udp_header *uh = dp_packet_l4(packet);
+
+ if (uh->udp_csum) {
+ uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr);
+ if (!uh->udp_csum) {
+ uh->udp_csum = htons(0xffff);
+ }
+ }
+ }
+ } else if (proto == IPPROTO_ICMPV6 &&
+ l4_size >= sizeof(struct icmp6_header)) {
+ struct icmp6_header *icmp = dp_packet_l4(packet);
+
+ icmp->icmp6_cksum = recalc_csum128(icmp->icmp6_cksum, addr, new_addr);
+ }
+}
+
+void
+packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,
+ ovs_16aligned_be32 addr[4],
+ const struct in6_addr *new_addr,
+ bool recalculate_csum)
+{
+ if (recalculate_csum) {
+ packet_update_csum128(packet, proto, addr, new_addr);
+ }
+ memcpy(addr, new_addr, sizeof(ovs_be32[4]));
+ pkt_metadata_init_conn(&packet->md);
+}
+
+/* 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 dp_packet *packet, ovs_be32 src, ovs_be32 dst,
+ uint8_t tos, uint8_t ttl)
+{
+ struct ip_header *nh = dp_packet_l3(packet);
+
+ if (get_16aligned_be32(&nh->ip_src) != src) {
+ packet_set_ipv4_addr(packet, &nh->ip_src, src);
+ }
+
+ if (get_16aligned_be32(&nh->ip_dst) != dst) {
+ packet_set_ipv4_addr(packet, &nh->ip_dst, dst);
+ }
+
+ if (nh->ip_tos != tos) {
+ uint8_t *field = &nh->ip_tos;
+
+ if (dp_packet_ip_checksum_valid(packet)) {
+ dp_packet_ip_checksum_set_partial(packet);
+ } else {
+ 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;
+
+ if (dp_packet_ip_checksum_valid(packet)) {
+ dp_packet_ip_checksum_set_partial(packet);
+ } else {
+ nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),
+ htons(ttl << 8));
+ }
+
+ *field = ttl;
+ }
+}
+
+/* Modifies the IPv6 header fields of 'packet' to be consistent with 'src',
+ * 'dst', 'traffic class', and 'next hop'. Updates 'packet''s L4 checksums as
+ * appropriate. 'packet' must contain a valid IPv6 packet with correctly
+ * populated l[34] offsets. */
+void
+packet_set_ipv6(struct dp_packet *packet, const struct in6_addr *src,
+ const struct in6_addr *dst, uint8_t key_tc, ovs_be32 key_fl,
+ uint8_t key_hl)
+{
+ struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);
+ bool recalc_csum = true;
+ uint8_t proto = 0;
+ bool rh_present;
+
+ rh_present = packet_rh_present(packet, &proto, &recalc_csum);
+
+ if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) {
+ packet_set_ipv6_addr(packet, proto, nh->ip6_src.be32,
+ src, recalc_csum);
+ }
+
+ if (memcmp(&nh->ip6_dst, dst, sizeof(ovs_be32[4]))) {
+ packet_set_ipv6_addr(packet, proto, nh->ip6_dst.be32, dst,
+ !rh_present && recalc_csum);
+ }
+
+ ip_set_ipv6_tc(&nh->ip6_flow, key_tc);
+ ip_set_ipv6_flow_label(&nh->ip6_flow, key_fl);
+ nh->ip6_hlim = key_hl;
+}
+
+static void
+packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)
+{
+ if (*port != new_port) {
+ if (csum) {
+ *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 offset properly populated. */
+void
+packet_set_tcp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
+{
+ struct tcp_header *th = dp_packet_l4(packet);
+ ovs_be16 *csum = NULL;
+
+ if (dp_packet_l4_checksum_valid(packet)) {
+ dp_packet_l4_checksum_set_partial(packet);
+ } else {
+ csum = &th->tcp_csum;
+ }
+
+ packet_set_port(&th->tcp_src, src, csum);
+ packet_set_port(&th->tcp_dst, dst, csum);
+ pkt_metadata_init_conn(&packet->md);
+}
+
+/* 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 offset properly populated. */
+void
+packet_set_udp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
+{
+ struct udp_header *uh = dp_packet_l4(packet);
+
+ if (dp_packet_l4_checksum_valid(packet)) {
+ dp_packet_l4_checksum_set_partial(packet);
+ packet_set_port(&uh->udp_src, src, NULL);
+ packet_set_port(&uh->udp_dst, dst, NULL);
+ } else {
+ ovs_be16 *csum = uh->udp_csum ? &uh->udp_csum : NULL;
+
+ packet_set_port(&uh->udp_src, src, csum);
+ packet_set_port(&uh->udp_dst, dst, csum);
+
+ if (csum && !uh->udp_csum) {
+ uh->udp_csum = htons(0xffff);
+ }
+ }
+
+ pkt_metadata_init_conn(&packet->md);
+}
+
+/* Sets the SCTP source and destination port ('src' and 'dst' respectively) of
+ * the SCTP header contained in 'packet'. 'packet' must be a valid SCTP packet
+ * with its l4 offset properly populated. */
+void
+packet_set_sctp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
+{
+ struct sctp_header *sh = dp_packet_l4(packet);
+
+ if (dp_packet_l4_checksum_valid(packet)) {
+ dp_packet_l4_checksum_set_partial(packet);
+ sh->sctp_src = src;
+ sh->sctp_dst = dst;
+ } else {
+ ovs_be32 old_csum, old_correct_csum, new_csum;
+ uint16_t tp_len = dp_packet_l4_size(packet);
+
+ old_csum = get_16aligned_be32(&sh->sctp_csum);
+ put_16aligned_be32(&sh->sctp_csum, 0);
+ old_correct_csum = crc32c((void *) sh, tp_len);
+
+ sh->sctp_src = src;
+ sh->sctp_dst = dst;
+
+ new_csum = crc32c((void *) sh, tp_len);
+ put_16aligned_be32(&sh->sctp_csum, old_csum ^ old_correct_csum
+ ^ new_csum);
+ }
+
+ pkt_metadata_init_conn(&packet->md);
+}
+
+/* Sets the ICMP type and code of the ICMP header contained in 'packet'.
+ * 'packet' must be a valid ICMP packet with its l4 offset properly
+ * populated. */
+void
+packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code)
+{
+ struct icmp_header *ih = dp_packet_l4(packet);
+ ovs_be16 orig_tc = htons(ih->icmp_type << 8 | ih->icmp_code);
+ ovs_be16 new_tc = htons(type << 8 | code);
+
+ if (orig_tc != new_tc) {
+ ih->icmp_type = type;
+ ih->icmp_code = code;
+
+ ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_tc, new_tc);
+ }
+ pkt_metadata_init_conn(&packet->md);
+}
+
+/* Sets the IGMP type to IGMP_HOST_MEMBERSHIP_QUERY and populates the
+ * v3 query header fields in 'packet'. 'packet' must be a valid IGMPv3
+ * query packet with its l4 offset properly populated.
+ */
+void
+packet_set_igmp3_query(struct dp_packet *packet, uint8_t max_resp,
+ ovs_be32 group, bool srs, uint8_t qrv, uint8_t qqic)
+{
+ struct igmpv3_query_header *igh = dp_packet_l4(packet);
+ ovs_be16 orig_type_max_resp =
+ htons(igh->type << 8 | igh->max_resp);
+ ovs_be16 new_type_max_resp =
+ htons(IGMP_HOST_MEMBERSHIP_QUERY << 8 | max_resp);
+
+ if (orig_type_max_resp != new_type_max_resp) {
+ igh->type = IGMP_HOST_MEMBERSHIP_QUERY;
+ igh->max_resp = max_resp;
+ igh->csum = recalc_csum16(igh->csum, orig_type_max_resp,
+ new_type_max_resp);
+ }
+
+ ovs_be32 old_group = get_16aligned_be32(&igh->group);
+
+ if (old_group != group) {
+ put_16aligned_be32(&igh->group, group);
+ igh->csum = recalc_csum32(igh->csum, old_group, group);
+ }
+
+ /* See RFC 3376 4.1.6. */
+ if (qrv > 7) {
+ qrv = 0;
+ }
+
+ ovs_be16 orig_srs_qrv_qqic = htons(igh->srs_qrv << 8 | igh->qqic);
+ ovs_be16 new_srs_qrv_qqic = htons(srs << 11 | qrv << 8 | qqic);
+
+ if (orig_srs_qrv_qqic != new_srs_qrv_qqic) {
+ igh->srs_qrv = (srs << 3 | qrv);
+ igh->qqic = qqic;
+ igh->csum = recalc_csum16(igh->csum, orig_srs_qrv_qqic,
+ new_srs_qrv_qqic);
+ }
+}
+
+void
+packet_set_nd_ext(struct dp_packet *packet, const ovs_16aligned_be32 rso_flags,
+ const uint8_t opt_type)
+{
+ struct ovs_nd_msg *ns;
+ struct ovs_nd_lla_opt *opt;
+ int bytes_remain = dp_packet_l4_size(packet);
+ struct ovs_16aligned_ip6_hdr * nh = dp_packet_l3(packet);
+ uint32_t pseudo_hdr_csum = 0;
+
+ if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {
+ return;
+ }
+
+ if (nh) {
+ pseudo_hdr_csum = ip_csum_pseudoheader6(nh);
+ }
+
+ ns = dp_packet_l4(packet);
+ opt = &ns->options[0];
+
+ /* set RSO flags and option type */
+ ns->rso_flags = rso_flags;
+ opt->type = opt_type;
+
+ /* recalculate checksum */
+ ovs_be16 *csum_value = &(ns->icmph.icmp6_cksum);
+ *csum_value = 0;
+ *csum_value = csum_finish(csum_continue(pseudo_hdr_csum,
+ &(ns->icmph), bytes_remain));
+
+}
+
+void
+packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,
+ const struct eth_addr sll, const struct eth_addr tll)
+{
+ struct ovs_nd_msg *ns;
+ struct ovs_nd_lla_opt *opt;
+ int bytes_remain = dp_packet_l4_size(packet);
+
+ if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {
+ return;
+ }
+
+ ns = dp_packet_l4(packet);
+ opt = &ns->options[0];
+ bytes_remain -= sizeof(*ns);
+
+ if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) {
+ packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, ns->target.be32, target,
+ true);
+ }
+
+ while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0
+ && bytes_remain >= (opt->len * ND_LLA_OPT_LEN)) {
+ if (opt->type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) {
+ if (!eth_addr_equals(opt->mac, sll)) {
+ ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
+
+ *csum = recalc_csum48(*csum, opt->mac, sll);
+ opt->mac = sll;
+ }
+
+ /* A packet can only contain one SLL or TLL option */
+ break;
+ } else if (opt->type == ND_OPT_TARGET_LINKADDR && opt->len == 1) {
+ if (!eth_addr_equals(opt->mac, tll)) {
+ ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
+
+ *csum = recalc_csum48(*csum, opt->mac, tll);
+ opt->mac = tll;
+ }
+
+ /* A packet can only contain one SLL or TLL option */
+ break;
+ }
+
+ opt += opt->len;
+ bytes_remain -= opt->len * ND_LLA_OPT_LEN;
+ }
+}
+
+#define ARP_PACKET_SIZE (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \
+ ARP_ETH_HEADER_LEN)
+
+/* Clears 'b' and replaces its contents by an ARP frame with the specified
+ * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'. The outer
+ * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination
+ * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if
+ * 'broadcast' is true. Points the L3 header to the ARP header. */
+void
+compose_arp(struct dp_packet *b, uint16_t arp_op,
+ const struct eth_addr arp_sha, const struct eth_addr arp_tha,
+ bool broadcast, ovs_be32 arp_spa, ovs_be32 arp_tpa)
+{
+ compose_arp__(b);
+
+ struct eth_header *eth = dp_packet_eth(b);
+ eth->eth_dst = broadcast ? eth_addr_broadcast : arp_tha;
+ eth->eth_src = arp_sha;
+
+ struct arp_eth_header *arp = dp_packet_l3(b);
+ arp->ar_op = htons(arp_op);
+ arp->ar_sha = arp_sha;
+ arp->ar_tha = arp_tha;
+ put_16aligned_be32(&arp->ar_spa, arp_spa);
+ put_16aligned_be32(&arp->ar_tpa, arp_tpa);
+}
+
+/* Clears 'b' and replaces its contents by an ARP frame. Sets the fields in
+ * the Ethernet and ARP headers that are fixed for ARP frames to those fixed
+ * values, and zeroes the other fields. Points the L3 header to the ARP
+ * header. */
+void
+compose_arp__(struct dp_packet *b)
+{
+ dp_packet_clear(b);
+ dp_packet_prealloc_tailroom(b, ARP_PACKET_SIZE);
+ dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
+
+ struct eth_header *eth = dp_packet_put_zeros(b, sizeof *eth);
+ eth->eth_type = htons(ETH_TYPE_ARP);
+
+ struct arp_eth_header *arp = dp_packet_put_zeros(b, sizeof *arp);
+ arp->ar_hrd = htons(ARP_HRD_ETHERNET);
+ arp->ar_pro = htons(ARP_PRO_IP);
+ arp->ar_hln = sizeof arp->ar_sha;
+ arp->ar_pln = sizeof arp->ar_spa;
+
+ dp_packet_set_l3(b, arp);
+
+ b->packet_type = htonl(PT_ETH);
+}
+
+/* This function expects packet with ethernet header with correct
+ * l3 pointer set. */
+void *
+compose_ipv6(struct dp_packet *packet, uint8_t proto,
+ const struct in6_addr *src, const struct in6_addr *dst,
+ uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size)
+{
+ struct ovs_16aligned_ip6_hdr *nh;
+ void *data;
+
+ nh = dp_packet_l3(packet);
+ nh->ip6_vfc = 0x60;
+ nh->ip6_nxt = proto;
+ nh->ip6_plen = htons(size);
+ data = dp_packet_put_zeros(packet, size);
+ dp_packet_set_l4(packet, data);
+ packet_set_ipv6(packet, src, dst, key_tc, key_fl, key_hl);
+ return data;
+}
+
+/* Compose an IPv6 Neighbor Discovery Neighbor Solicitation message. */
+void
+compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src,
+ const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst)
+{
+ struct in6_addr sn_addr;
+ struct eth_addr eth_dst;
+ struct ovs_nd_msg *ns;
+ struct ovs_nd_lla_opt *lla_opt;
+ uint32_t icmp_csum;
+
+ in6_addr_solicited_node(&sn_addr, ipv6_dst);
+ ipv6_multicast_to_ethernet(ð_dst, &sn_addr);
+
+ eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
+ ns = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, &sn_addr,
+ 0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);
+
+ ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
+ ns->icmph.icmp6_code = 0;
+ put_16aligned_be32(&ns->rso_flags, htonl(0));
+
+ lla_opt = &ns->options[0];
+ lla_opt->type = ND_OPT_SOURCE_LINKADDR;
+ lla_opt->len = 1;
+
+ packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero);
+
+ ns->icmph.icmp6_cksum = 0;
+ icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
+ ns->icmph.icmp6_cksum = csum_finish(
+ csum_continue(icmp_csum, ns, ND_MSG_LEN + ND_LLA_OPT_LEN));
+}
+
+/* Compose an IPv6 Neighbor Discovery Neighbor Advertisement message. */
+void
+compose_nd_na(struct dp_packet *b,
+ const struct eth_addr eth_src, const struct eth_addr eth_dst,
+ const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,
+ ovs_be32 rso_flags)
+{
+ struct ovs_nd_msg *na;
+ struct ovs_nd_lla_opt *lla_opt;
+ uint32_t icmp_csum;
+
+ eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
+ na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst,
+ 0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);
+
+ na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;
+ na->icmph.icmp6_code = 0;
+ put_16aligned_be32(&na->rso_flags, rso_flags);
+
+ lla_opt = &na->options[0];
+ lla_opt->type = ND_OPT_TARGET_LINKADDR;
+ lla_opt->len = 1;
+
+ packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src);
+
+ na->icmph.icmp6_cksum = 0;
+ icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
+ na->icmph.icmp6_cksum = csum_finish(csum_continue(
+ icmp_csum, na, ND_MSG_LEN + ND_LLA_OPT_LEN));
+}
+
+/* Compose an IPv6 Neighbor Discovery Router Advertisement message with
+ * Source Link-layer Address Option and MTU Option.
+ * Caller can call packet_put_ra_prefix_opt to append Prefix Information
+ * Options to composed messags in 'b'. */
+void
+compose_nd_ra(struct dp_packet *b,
+ const struct eth_addr eth_src, const struct eth_addr eth_dst,
+ const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,
+ uint8_t cur_hop_limit, uint8_t mo_flags,
+ ovs_be16 router_lt, ovs_be32 reachable_time,
+ ovs_be32 retrans_timer, uint32_t mtu)
+{
+ /* Don't compose Router Advertisement packet with MTU Option if mtu
+ * value is 0. */
+ bool with_mtu = mtu != 0;
+ size_t mtu_opt_len = with_mtu ? ND_MTU_OPT_LEN : 0;
+
+ eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
+
+ struct ovs_ra_msg *ra = compose_ipv6(
+ b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255,
+ RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len);
+ ra->icmph.icmp6_type = ND_ROUTER_ADVERT;
+ ra->icmph.icmp6_code = 0;
+ ra->cur_hop_limit = cur_hop_limit;
+ ra->mo_flags = mo_flags;
+ ra->router_lifetime = router_lt;
+ ra->reachable_time = reachable_time;
+ ra->retrans_timer = retrans_timer;
+
+ struct ovs_nd_lla_opt *lla_opt = ra->options;
+ lla_opt->type = ND_OPT_SOURCE_LINKADDR;
+ lla_opt->len = 1;
+ lla_opt->mac = eth_src;
+
+ if (with_mtu) {
+ /* ovs_nd_mtu_opt has the same size with ovs_nd_lla_opt. */
+ struct ovs_nd_mtu_opt *mtu_opt
+ = (struct ovs_nd_mtu_opt *)(lla_opt + 1);
+ mtu_opt->type = ND_OPT_MTU;
+ mtu_opt->len = 1;
+ mtu_opt->reserved = 0;
+ put_16aligned_be32(&mtu_opt->mtu, htonl(mtu));
+ }
+
+ ra->icmph.icmp6_cksum = 0;
+ uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
+ ra->icmph.icmp6_cksum = csum_finish(csum_continue(
+ icmp_csum, ra, RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len));
+}
+
+/* Append an IPv6 Neighbor Discovery Prefix Information option to a
+ * Router Advertisement message. */
+void
+packet_put_ra_prefix_opt(struct dp_packet *b,
+ uint8_t plen, uint8_t la_flags,
+ ovs_be32 valid_lifetime, ovs_be32 preferred_lifetime,
+ const ovs_be128 prefix)
+{
+ size_t prev_l4_size = dp_packet_l4_size(b);
+ struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(b);
+ nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN);
+
+ struct ovs_nd_prefix_opt *prefix_opt =
+ dp_packet_put_uninit(b, sizeof *prefix_opt);
+ prefix_opt->type = ND_OPT_PREFIX_INFORMATION;
+ prefix_opt->len = 4;
+ prefix_opt->prefix_len = plen;
+ prefix_opt->la_flags = la_flags;
+ put_16aligned_be32(&prefix_opt->valid_lifetime, valid_lifetime);
+ put_16aligned_be32(&prefix_opt->preferred_lifetime, preferred_lifetime);
+ put_16aligned_be32(&prefix_opt->reserved, 0);
+ memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4]));
+
+ struct ovs_ra_msg *ra = dp_packet_l4(b);
+ ra->icmph.icmp6_cksum = 0;
+ uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
+ ra->icmph.icmp6_cksum = csum_finish(csum_continue(
+ icmp_csum, ra, prev_l4_size + ND_PREFIX_OPT_LEN));
+}
+
+void
+IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6)
+{
+ if (is_ipv6) {
+ ovs_16aligned_be32 *ip6 = dp_packet_l3(pkt);
+
+ put_16aligned_be32(ip6, get_16aligned_be32(ip6) |
+ htonl(IP_ECN_CE << 20));
+ } else {
+ struct ip_header *nh = dp_packet_l3(pkt);
+ uint8_t tos = nh->ip_tos;
+
+ tos |= IP_ECN_CE;
+ if (nh->ip_tos != tos) {
+ if (dp_packet_ip_checksum_valid(pkt)) {
+ dp_packet_ip_checksum_set_partial(pkt);
+ } else {
+ nh->ip_csum = recalc_csum16(nh->ip_csum, htons(nh->ip_tos),
+ htons((uint16_t) tos));
+ }
+
+ nh->ip_tos = tos;
+ }
+ }
+}
+
+/* Set TCP checksum field in packet 'p' with complete checksum.
+ * The packet must have the L3 and L4 offsets. */
+void
+packet_tcp_complete_csum(struct dp_packet *p, bool inner)
+{
+ struct tcp_header *tcp;
+ size_t tcp_sz;
+ void *ip_hdr;
+
+ if (inner) {
+ tcp = dp_packet_inner_l4(p);
+ ip_hdr = dp_packet_inner_l3(p);
+ tcp_sz = dp_packet_inner_l4_size(p);
+ } else {
+ tcp = dp_packet_l4(p);
+ ip_hdr = dp_packet_l3(p);
+ tcp_sz = dp_packet_l4_size(p);
+ }
+
+ ovs_assert(tcp);
+ ovs_assert(ip_hdr);
+
+ tcp->tcp_csum = 0;
+ if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {
+ struct ip_header *ip = ip_hdr;
+
+ tcp->tcp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),
+ tcp, tcp_sz));
+ } else {
+ struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;
+
+ tcp->tcp_csum = ip_csum_upperlayer6(ip6, tcp, ip6->ip6_nxt,
+ tcp_sz);
+ }
+
+ if (inner) {
+ dp_packet_inner_l4_checksum_set_good(p);
+ } else {
+ dp_packet_l4_checksum_set_good(p);
+ }
+}
+
+/* Set UDP checksum field in packet 'p' with complete checksum.
+ * The packet must have the L3 and L4 offsets. */
+void
+packet_udp_complete_csum(struct dp_packet *p, bool inner)
+{
+ struct udp_header *udp;
+ size_t udp_sz;
+ void *ip_hdr;
+
+ if (inner) {
+ udp = dp_packet_inner_l4(p);
+ ip_hdr = dp_packet_inner_l3(p);
+ udp_sz = dp_packet_inner_l4_size(p);
+ } else {
+ udp = dp_packet_l4(p);
+ ip_hdr = dp_packet_l3(p);
+ udp_sz = dp_packet_l4_size(p);
+ }
+
+ ovs_assert(udp);
+ ovs_assert(ip_hdr);
+
+ /* Skip csum calculation if the udp_csum is zero. */
+ if (!udp->udp_csum) {
+ goto out;
+ }
+
+ udp->udp_csum = 0;
+ if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {
+ struct ip_header *ip = ip_hdr;
+
+ udp->udp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),
+ udp, udp_sz));
+ } else {
+ struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;
+
+ udp->udp_csum = ip_csum_upperlayer6(ip6, udp, ip6->ip6_nxt,
+ udp_sz);
+ }
+
+ if (!udp->udp_csum) {
+ udp->udp_csum = htons(0xffff);
+ }
+
+out:
+ if (inner) {
+ dp_packet_inner_l4_checksum_set_good(p);
+ } else {
+ dp_packet_l4_checksum_set_good(p);
+ }
+}
+
+/* This helper computes a "constant" UDP checksum without looking at the
+ * L4 payload.
+ *
+ * This is possible when L4 is either TCP or UDP: the L4 payload checksum
+ * is either computed in SW or in HW later, but its contribution to the
+ * outer checksum is cancelled by the L4 payload being part of the global
+ * packet sum. */
+bool
+packet_udp_tunnel_csum(struct dp_packet *p)
+{
+ struct ip_header *inner_ip;
+ const void *inner_l4_data;
+ char *after_inner_l4_csum;
+ size_t inner_l4_csum_off;
+ struct udp_header *udp;
+ ovs_be16 inner_l4_csum;
+ uint32_t partial_csum;
+ struct ip_header *ip;
+ uint32_t inner_csum;
+ uint16_t tso_segsz;
+ bool inner_ipv4;
+ void *inner_l4;
+
+ inner_ip = dp_packet_inner_l3(p);
+ inner_l4 = dp_packet_inner_l4(p);
+ ip = dp_packet_l3(p);
+ udp = dp_packet_l4(p);
+
+ if (dp_packet_inner_l4_proto_tcp(p)) {
+ inner_l4_csum_off = offsetof(struct tcp_header, tcp_csum);
+ inner_l4_data = dp_packet_get_inner_tcp_payload(p);
+ if (!inner_l4_data) {
+ /* Malformed packet. */
+ return false;
+ }
+ } else if (dp_packet_inner_l4_proto_udp(p)) {
+ inner_l4_csum_off = offsetof(struct udp_header, udp_csum);
+ inner_l4_data = (char *) inner_l4 + sizeof (struct udp_header);
+ if (((struct udp_header *) inner_l4)->udp_csum == 0) {
+ /* There is no nested checksum.
+ * No choice but compute a full checksum. */
+ return false;
+ }
+ } else {
+ /* This optimisation applies only to inner TCP/UDP. */
+ return false;
+ }
+
+ if (!dp_packet_inner_l4_checksum_valid(p)) {
+ /* We have no idea about the contribution of the payload data
+ * and what the L4 checksum put in the packet data looks like.
+ * Simpler is to let a full checksum happen. */
+ return false;
+ }
+
+ inner_ipv4 = IP_VER(inner_ip->ip_ihl_ver) == 4;
+ if (inner_ipv4) {
+ inner_csum = ip_csum_pseudoheader(inner_ip);
+ } else {
+ struct ovs_16aligned_ip6_hdr *inner_ip6 = dp_packet_inner_l3(p);
+
+ inner_csum = ip_csum_pseudoheader6(inner_ip6);
+ }
+
+ inner_csum = csum_continue(inner_csum, inner_l4, inner_l4_csum_off);
+ after_inner_l4_csum = (char *) inner_l4 + inner_l4_csum_off + 2;
+ inner_l4_csum = csum_finish(csum_continue(inner_csum, after_inner_l4_csum,
+ (char *) inner_l4_data - after_inner_l4_csum));
+ /* Important: for inner UDP, a null inner_l4_csum here should in theory be
+ * replaced with 0xffff. However, since the only use of inner_l4_csum is
+ * for the final outer checksum with a csum_add16() below, we can skip this
+ * entirely because adding 0xffff will have the same effect as adding 0x0
+ * after reducing in csum_finish. */
+
+ udp->udp_csum = 0;
+ if (IP_VER(ip->ip_ihl_ver) == 4) {
+ partial_csum = ip_csum_pseudoheader(ip);
+ } else {
+ struct ovs_16aligned_ip6_hdr *ip6 = dp_packet_l3(p);
+
+ partial_csum = ip_csum_pseudoheader6(ip6);
+ }
+
+ partial_csum = csum_continue(partial_csum, udp,
+ (char *) inner_ip - (char *) udp);
+ if (!inner_ipv4 || !dp_packet_inner_ip_checksum_valid(p)) {
+ /* IPv6 has no checksum, so for inner IPv6, we need to sum the header.
+ *
+ * In IPv4 case, if inner checksum is already good or HW offload
+ * has been requested, the (final) sum of the IPv4 header will be 0.
+ * Otherwise, we need to sum the header like for IPv6. */
+ partial_csum = csum_continue(partial_csum, inner_ip,
+ (char *) inner_l4 - (char *) inner_ip);
+ }
+ partial_csum = csum_continue(partial_csum, inner_l4, inner_l4_csum_off);
+ partial_csum = csum_add16(partial_csum, inner_l4_csum);
+ partial_csum = csum_continue(partial_csum, after_inner_l4_csum,
+ (char *) inner_l4_data - after_inner_l4_csum);
+ udp->udp_csum = csum_finish(partial_csum);
+ tso_segsz = dp_packet_get_tso_segsz(p);
+ if (tso_segsz) {
+ uint16_t payload_len = dp_packet_get_inner_tcp_payload_length(p);
+
+ ovs_assert(payload_len == tso_segsz * dp_packet_gso_nr_segs(p));
+
+ /* The pseudo header used in the outer UDP checksum is dependent on
+ * the ip_tot_len / ip6_plen which was a reflection of the TSO frame
+ * size. The segmented packet will be shorter. */
+ udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),
+ htons(tso_segsz));
+
+ /* When segmenting the packet, various headers get updated:
+ * - inner L3
+ * - for IPv4, ip_tot_len is updated, BUT it is not affecting the
+ * outer UDP checksum because the IPv4 header itself contains
+ * a checksum that compensates for this update,
+ * - for IPv6, ip6_plen is updated, and this must be considered,
+ * - inner L4
+ * - inner pseudo header used in the TCP checksum is dependent on
+ * the inner ip_tot_len / ip6_plen,
+ * - TCP seq number is updated,
+ * - the HW may change some TCP flags (think PSH/FIN),
+ * BUT the TCP checksum will compensate for those updates,
+ *
+ * Summary: we only care about the inner IPv6 header update.
+ */
+ if (IP_VER(inner_ip->ip_ihl_ver) != 4) {
+ udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),
+ htons(tso_segsz));
+ }
+ }
+ if (!udp->udp_csum) {
+ udp->udp_csum = htons(0xffff);
+ }
+ dp_packet_l4_checksum_set_good(p);
+
+ return true;
+}
+
+/* Set SCTP checksum field in packet 'p' with complete checksum.
+ * The packet must have the L3 and L4 offsets. */
+void
+packet_sctp_complete_csum(struct dp_packet *p, bool inner)
+{
+ struct sctp_header *sh;
+ uint16_t tp_len;
+ ovs_be32 csum;
+
+ if (inner) {
+ sh = dp_packet_inner_l4(p);
+ tp_len = dp_packet_inner_l4_size(p);
+ } else {
+ sh = dp_packet_l4(p);
+ tp_len = dp_packet_l4_size(p);
+ }
+
+ ovs_assert(sh);
+
+ put_16aligned_be32(&sh->sctp_csum, 0);
+ csum = crc32c((void *) sh, tp_len);
+ put_16aligned_be32(&sh->sctp_csum, csum);
+
+ if (inner) {
+ dp_packet_inner_l4_checksum_set_good(p);
+ } else {
+ dp_packet_l4_checksum_set_good(p);
+ }
+}
@@ -17,22 +17,34 @@
#ifndef DPBUF_H
#define DPBUF_H 1
+#include <inttypes.h>
+#include <sys/types.h>
#include <stddef.h>
#include <stdint.h>
+#include <string.h>
#ifdef DPDK_NETDEV
#include <rte_config.h>
#include <rte_mbuf.h>
#endif
+#include "compiler.h"
#include "csum.h"
+#include "flow.h"
+#include "openvswitch/geneve.h"
+#include "hash.h"
+#include "openvswitch/list.h"
#include "netdev-afxdp.h"
#include "netdev-dpdk.h"
#include "net-proto.h"
-#include "openvswitch/list.h"
-#include "packets.h"
+#include "openvswitch/nsh.h"
+#include "odp-netlink.h"
+#include "openvswitch/packets.h"
+#include "random.h"
+#include "timeval.h"
+#include "openvswitch/types.h"
#include "util.h"
-#include "flow.h"
+#include "unaligned.h"
#ifdef __cplusplus
extern "C" {
@@ -1504,6 +1516,94 @@ dp_packet_update_rss_hash_ipv6_tcp_udp(struct dp_packet *packet)
dp_packet_set_rss_hash(packet, hash);
}
+
+void compose_rarp(struct dp_packet *, const struct eth_addr);
+
+void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci);
+void eth_pop_vlan(struct dp_packet *);
+
+const char *eth_from_hex(const char *hex, struct dp_packet **packetp);
+
+void set_mpls_lse(struct dp_packet *, ovs_be32 label);
+void push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse);
+void pop_mpls(struct dp_packet *, ovs_be16 ethtype);
+void add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,
+ bool l3_encap);
+
+
+void push_eth(struct dp_packet *packet, const struct eth_addr *dst,
+ const struct eth_addr *src);
+void pop_eth(struct dp_packet *packet);
+
+void push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src);
+bool pop_nsh(struct dp_packet *packet);
+
+void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst,
+ const struct eth_addr eth_src, uint16_t eth_type,
+ size_t size);
+void *snap_compose(struct dp_packet *, const struct eth_addr eth_dst,
+ const struct eth_addr eth_src,
+ unsigned int oui, uint16_t snap_type, size_t size);
+void packet_set_ipv4(struct dp_packet *, ovs_be32 src, ovs_be32 dst, uint8_t tos,
+ uint8_t ttl);
+void packet_set_ipv4_addr(struct dp_packet *packet, ovs_16aligned_be32 *addr,
+ ovs_be32 new_addr);
+void packet_set_ipv6(struct dp_packet *, const struct in6_addr *src,
+ const struct in6_addr *dst, uint8_t tc,
+ ovs_be32 fl, uint8_t hlmit);
+void packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,
+ ovs_16aligned_be32 addr[4],
+ const struct in6_addr *new_addr,
+ bool recalculate_csum);
+void packet_set_tcp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
+void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
+void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
+void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code);
+void packet_set_nd(struct dp_packet *, const struct in6_addr *target,
+ const struct eth_addr sll, const struct eth_addr tll);
+void packet_set_nd_ext(struct dp_packet *packet,
+ const ovs_16aligned_be32 rso_flags,
+ const uint8_t opt_type);
+void packet_set_igmp3_query(struct dp_packet *, uint8_t max_resp,
+ ovs_be32 group, bool srs, uint8_t qrv,
+ uint8_t qqic);
+void *compose_ipv6(struct dp_packet *packet, uint8_t proto,
+ const struct in6_addr *src, const struct in6_addr *dst,
+ uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size);
+void compose_arp__(struct dp_packet *);
+void compose_arp(struct dp_packet *, uint16_t arp_op,
+ const struct eth_addr arp_sha,
+ const struct eth_addr arp_tha, bool broadcast,
+ ovs_be32 arp_spa, ovs_be32 arp_tpa);
+void compose_nd_ns(struct dp_packet *, const struct eth_addr eth_src,
+ const struct in6_addr *ipv6_src,
+ const struct in6_addr *ipv6_dst);
+void compose_nd_na(struct dp_packet *, const struct eth_addr eth_src,
+ const struct eth_addr eth_dst,
+ const struct in6_addr *ipv6_src,
+ const struct in6_addr *ipv6_dst,
+ ovs_be32 rso_flags);
+void compose_nd_ra(struct dp_packet *,
+ const struct eth_addr eth_src,
+ const struct eth_addr eth_dst,
+ const struct in6_addr *ipv6_src,
+ const struct in6_addr *ipv6_dst,
+ uint8_t cur_hop_limit, uint8_t mo_flags,
+ ovs_be16 router_lt, ovs_be32 reachable_time,
+ ovs_be32 retrans_timer, uint32_t mtu);
+void packet_put_ra_prefix_opt(struct dp_packet *,
+ uint8_t plen, uint8_t la_flags,
+ ovs_be32 valid_lifetime,
+ ovs_be32 preferred_lifetime,
+ const ovs_be128 router_prefix);
+bool packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr,
+ bool *first_frag);
+void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6);
+void packet_tcp_complete_csum(struct dp_packet *, bool is_inner);
+void packet_udp_complete_csum(struct dp_packet *, bool is_inner);
+bool packet_udp_tunnel_csum(struct dp_packet *);
+void packet_sctp_complete_csum(struct dp_packet *, bool is_inner);
+
#ifdef __cplusplus
}
#endif
@@ -43,7 +43,6 @@
#include "odp-util.h"
#include "openvswitch/ofpbuf.h"
#include "openvswitch/ofp-ct.h"
-#include "packets.h"
#include "openvswitch/shash.h"
#include "simap.h"
#include "smap.h"
@@ -48,7 +48,6 @@
#include "dpif-netdev-private-extract.h"
#include "dpif-netdev-private-flow.h"
#include "dp-packet.h"
-#include "packets.h"
/* AVX512-BW level permutex2var_epi8 emulation. */
static inline __m512i
@@ -19,6 +19,7 @@
#include "dpif-netdev-lookup.h"
#include "cpu.h"
+#include "openvswitch/dynamic-string.h"
#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(dpif_netdev_lookup);
@@ -24,6 +24,7 @@
#include "dpif-netdev-private-dpcls.h"
#include "dpif-netdev-private-extract.h"
#include "dpif-netdev-private-thread.h"
+#include "openvswitch/dynamic-string.h"
#include "flow.h"
#include "openvswitch/vlog.h"
#include "ovs-thread.h"
@@ -25,6 +25,7 @@
#include <stdint.h>
#include "cmap.h"
+#include "netlink-protocol.h"
#include "openvswitch/thread.h"
#ifdef __cplusplus
@@ -74,7 +74,6 @@
#include "openvswitch/vlog.h"
#include "ovs-numa.h"
#include "ovs-rcu.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "pvector.h"
#include "random.h"
@@ -23,7 +23,6 @@
#include "dpif.h"
#include "openvswitch/types.h"
#include "dp-packet.h"
-#include "packets.h"
#ifdef __cplusplus
extern "C" {
@@ -24,6 +24,7 @@
#include "dpif-netlink.h"
#include "netdev-vport.h"
+#include "netlink.h"
#include "netlink-socket.h"
#include "openvswitch/vlog.h"
@@ -58,7 +58,6 @@
#include "openvswitch/thread.h"
#include "openvswitch/usdt-probes.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
#include "random.h"
#include "sset.h"
#include "timeval.h"
@@ -27,13 +27,14 @@
#include "dpif-netdev.h"
#include "dpif-offload.h"
#include "dpif-offload-dpdk-private.h"
+#include "openvswitch/dynamic-string.h"
#include "netdev-provider.h"
#include "netdev-vport.h"
+#include "netlink.h"
#include "odp-util.h"
#include "openvswitch/match.h"
#include "openvswitch/vlog.h"
#include "ovs-rcu.h"
-#include "packets.h"
#include "uuid.h"
VLOG_DEFINE_THIS_MODULE(dpif_offload_dpdk_netdev);
@@ -20,11 +20,14 @@
#include "dpif-offload.h"
#include "dpif-offload-provider.h"
#include "dpif-offload-dpdk-private.h"
+#include "openvswitch/dynamic-string.h"
#include "id-fpool.h"
#include "mov-avg.h"
#include "mpsc-queue.h"
#include "netdev-provider.h"
#include "netdev-vport.h"
+#include "net-proto.h"
+#include "openvswitch/ofpbuf.h"
#include "util.h"
#include "uuid.h"
@@ -35,7 +35,6 @@
#include "netlink.h"
#include "odp-execute.h"
#include "odp-util.h"
-#include "packets.h"
#include "route-table.h"
#include "seq.h"
#include "sset.h"
@@ -384,7 +384,6 @@
#include "openflow/openflow.h"
#include "openvswitch/ofp-meter.h"
#include "ovs-numa.h"
-#include "packets.h"
#include "util.h"
#ifdef __cplusplus
@@ -36,7 +36,6 @@
#include "openvswitch/match.h"
#include "dp-packet.h"
#include "openflow/openflow.h"
-#include "packets.h"
#include "odp-util.h"
#include "random.h"
#include "unaligned.h"
@@ -44,6 +43,7 @@
#include "openvswitch/nsh.h"
#include "ovs-router.h"
#include "lib/netdev-provider.h"
+#include "tun-metadata.h"
#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(flow);
@@ -30,8 +30,8 @@
#include "openflow/openflow.h"
#include "openvswitch/flow.h"
#include "net-proto.h"
-#include "packets.h"
#include "hash.h"
+#include "odp-netlink.h"
#include "util.h"
struct dpif_flow_stats;
@@ -973,6 +973,161 @@ static inline bool is_ct_valid(const struct flow *flow,
return flow->ct_state & CS_VALID_MASK;
}
+/* Purely internal to OVS userspace. These flags should never be exposed to
+ * the outside world and so aren't included in the flags mask. */
+
+/* Tunnel information is in userspace datapath format. */
+#define FLOW_TNL_F_UDPIF (1 << 4)
+
+static inline bool
+flow_tnl_dst_is_set(const struct flow_tnl *tnl)
+{
+ return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst);
+}
+
+static inline bool
+flow_tnl_src_is_set(const struct flow_tnl *tnl)
+{
+ return tnl->ip_src || ipv6_addr_is_set(&tnl->ipv6_src);
+}
+
+struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl);
+struct in6_addr flow_tnl_src(const struct flow_tnl *tnl);
+
+/* Returns an offset to 'src' covering all the meaningful fields in 'src'. */
+static inline size_t
+flow_tnl_size(const struct flow_tnl *src)
+{
+ if (!flow_tnl_dst_is_set(src)) {
+ /* Covers ip_dst and ipv6_dst only. */
+ return offsetof(struct flow_tnl, ip_src);
+ }
+ if (src->flags & FLOW_TNL_F_UDPIF) {
+ /* Datapath format, cover all options we have. */
+ return offsetof(struct flow_tnl, metadata.opts)
+ + src->metadata.present.len;
+ }
+ if (!src->metadata.present.map) {
+ /* No TLVs, opts is irrelevant. */
+ return offsetof(struct flow_tnl, metadata.opts);
+ }
+ /* Have decoded TLVs, opts is relevant. */
+ return sizeof *src;
+}
+
+/* Copy flow_tnl, but avoid copying unused portions of tun_metadata. Unused
+ * data in 'dst' is NOT cleared, so this must not be used in cases where the
+ * uninitialized portion may be hashed over. */
+static inline void
+flow_tnl_copy__(struct flow_tnl *dst, const struct flow_tnl *src)
+{
+ memcpy(dst, src, flow_tnl_size(src));
+}
+
+/* Fwd declare conn here. */
+struct conn;
+
+/* Datapath packet metadata */
+struct pkt_metadata {
+PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,
+ uint32_t recirc_id; /* Recirculation id carried with the
+ recirculating packets. 0 for packets
+ received from the wire. */
+ uint32_t dp_hash; /* hash value computed by the recirculation
+ action. */
+ uint32_t skb_priority; /* Packet priority for QoS. */
+ uint32_t pkt_mark; /* Packet mark. */
+ uint8_t ct_state; /* Connection state. */
+ bool ct_orig_tuple_ipv6;
+ uint16_t ct_zone; /* Connection zone. */
+ uint32_t ct_mark; /* Connection mark. */
+ ovs_u128 ct_label; /* Connection label. */
+ union flow_in_port in_port; /* Input port. */
+ odp_port_t orig_in_port; /* Originating in_port for tunneled packets */
+ struct conn *conn; /* Cached conntrack connection. */
+ bool reply; /* True if reply direction. */
+ bool icmp_related; /* True if ICMP related. */
+);
+
+PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline1,
+ union { /* Populated only for non-zero 'ct_state'. */
+ struct ovs_key_ct_tuple_ipv4 ipv4;
+ struct ovs_key_ct_tuple_ipv6 ipv6; /* Used only if */
+ } ct_orig_tuple; /* 'ct_orig_tuple_ipv6' is set */
+);
+
+PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline2,
+ struct flow_tnl tunnel; /* Encapsulating tunnel parameters. Note that
+ * if 'ip_dst' == 0, the rest of the fields may
+ * be uninitialized. */
+);
+};
+
+BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline0) == 0);
+BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline1) ==
+ CACHE_LINE_SIZE);
+BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline2) ==
+ 2 * CACHE_LINE_SIZE);
+
+static inline void
+pkt_metadata_init_tnl(struct pkt_metadata *md)
+{
+ odp_port_t orig_in_port;
+
+ /* Zero up through the tunnel metadata options. The length and table
+ * are before this and as long as they are empty, the options won't
+ * be looked at. Keep the orig_in_port field. */
+ orig_in_port = md->in_port.odp_port;
+ memset(md, 0, offsetof(struct pkt_metadata, tunnel.metadata.opts));
+ md->orig_in_port = orig_in_port;
+}
+
+static inline void
+pkt_metadata_init_conn(struct pkt_metadata *md)
+{
+ md->conn = NULL;
+}
+
+static inline void
+pkt_metadata_init(struct pkt_metadata *md, odp_port_t port)
+{
+ /* This is called for every packet in userspace datapath and affects
+ * performance if all the metadata is initialized. Hence, fields should
+ * only be zeroed out when necessary.
+ *
+ * Initialize only till ct_state. Once the ct_state is zeroed out rest
+ * of ct fields will not be looked at unless ct_state != 0.
+ */
+ memset(md, 0, offsetof(struct pkt_metadata, ct_orig_tuple_ipv6));
+
+ /* It can be expensive to zero out all of the tunnel metadata. However,
+ * we can just zero out ip_dst and the rest of the data will never be
+ * looked at. */
+ md->tunnel.ip_dst = 0;
+ md->tunnel.ipv6_dst = in6addr_any;
+ md->in_port.odp_port = port;
+ md->orig_in_port = port;
+ md->conn = NULL;
+}
+
+/* This function prefetches the cachelines touched by pkt_metadata_init()
+ * and pkt_metadata_init_tnl(). For performance reasons the two functions
+ * should be kept in sync. */
+static inline void
+pkt_metadata_prefetch_init(struct pkt_metadata *md)
+{
+ /* Prefetch cacheline0 as members till ct_state and odp_port will
+ * be initialized later in pkt_metadata_init(). */
+ OVS_PREFETCH(md->cacheline0);
+
+ /* Prefetch cacheline1 as members of this cacheline will be zeroed out
+ * in pkt_metadata_init_tnl(). */
+ OVS_PREFETCH(md->cacheline1);
+
+ /* Prefetch cachline2 as ip_dst & ipv6_dst fields will be initialized. */
+ OVS_PREFETCH(md->cacheline2);
+}
+
static inline void
pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow)
{
@@ -25,6 +25,7 @@
#include "coverage.h"
#include "csum.h"
+#include "openvswitch/dynamic-string.h"
#include "ipf.h"
#include "latch.h"
#include "openvswitch/hmap.h"
@@ -32,7 +33,6 @@
#include "openvswitch/types.h"
#include "openvswitch/vlog.h"
#include "ovs-atomic.h"
-#include "packets.h"
#include "util.h"
VLOG_DEFINE_THIS_MODULE(ipf);
@@ -24,7 +24,6 @@
#include "openvswitch/hmap.h"
#include "dp-packet.h"
#include "ovs-atomic.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "seq.h"
#include "openvswitch/shash.h"
@@ -18,8 +18,12 @@
#define LACP_H 1
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
-#include "packets.h"
+
+#include "net-proto.h"
+
+struct dp_packet;
/* LACP Protocol Implementation. */
@@ -27,7 +27,6 @@
#include <sys/types.h>
#include "compiler.h"
#include "dp-packet.h"
-#include "packets.h"
VLOG_DEFINE_THIS_MODULE(lldp);
@@ -25,7 +25,6 @@
#include <sys/socket.h>
#include "aa-structs.h"
#include "lldp-const.h"
-#include "packets.h"
enum {
LLDPD_AF_UNSPEC = 0,
@@ -42,7 +42,6 @@
#include "compiler.h"
#include "openvswitch/dynamic-string.h"
#include "openvswitch/list.h"
-#include "packets.h"
#include "timeval.h"
VLOG_DEFINE_THIS_MODULE(lldpd);
@@ -28,7 +28,6 @@
#include "openvswitch/list.h"
#include "lldpd-structs.h"
#include "lldp-tlv.h"
-#include "packets.h"
#include "openvswitch/vlog.h"
#define ETHERTYPE_LLDP 0x88cc
@@ -23,8 +23,10 @@
#include "bitmap.h"
#include "coverage.h"
#include "hash.h"
+#include "net-proto.h"
#include "openvswitch/list.h"
#include "openvswitch/poll-loop.h"
+#include "random.h"
#include "timeval.h"
#include "unaligned.h"
#include "util.h"
@@ -23,7 +23,6 @@
#include "openvswitch/list.h"
#include "ovs-atomic.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "timeval.h"
/* MAC learning table
@@ -23,7 +23,6 @@
#include "openvswitch/dynamic-string.h"
#include "openvswitch/meta-flow.h"
#include "openvswitch/ofp-port.h"
-#include "packets.h"
#include "tun-metadata.h"
#include "openvswitch/nsh.h"
@@ -25,7 +25,6 @@
#include "openvswitch/list.h"
#include "ovs-atomic.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "timeval.h"
struct mcast_snooping;
@@ -29,7 +29,6 @@
#include "ovs-atomic.h"
#include "ovs-rcu.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "random.h"
#include "openvswitch/shash.h"
#include "socket-util.h"
@@ -27,7 +27,6 @@
#include "openvswitch/dynamic-string.h"
#include "openvswitch/ofp-actions.h"
#include "openvswitch/ofp-errors.h"
-#include "packets.h"
#include "util.h"
/* Checks that 'mp' is valid on flow. Returns 0 if it is valid, otherwise an
@@ -52,7 +52,6 @@
#include "openvswitch/vlog.h"
#include "ovs-atomic.h"
#include "ovs-numa.h"
-#include "packets.h"
#include "socket-util.h"
#include "util.h"
@@ -55,7 +55,6 @@
#include "fatal-signal.h"
#include "openflow/openflow.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "openvswitch/shash.h"
#include "socket-util.h"
@@ -66,7 +66,6 @@
#include "ovs-numa.h"
#include "ovs-rcu.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "smap.h"
#include "sset.h"
#include "timeval.h"
@@ -34,7 +34,6 @@
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"
#include "ovs-atomic.h"
-#include "packets.h"
#include "pcap-file.h"
#include "openvswitch/poll-loop.h"
#include "openvswitch/shash.h"
@@ -68,7 +68,6 @@
#include "openflow/openflow.h"
#include "ovs-atomic.h"
#include "ovs-numa.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "rtnetlink.h"
#include "openvswitch/shash.h"
@@ -36,12 +36,14 @@
#include "coverage.h"
#include "csum.h"
#include "dp-packet.h"
+#include "openvswitch/dynamic-string.h"
#include "netdev.h"
+#include "net-proto.h"
#include "netdev-vport.h"
#include "netdev-vport-private.h"
#include "odp-netlink.h"
-#include "packets.h"
#include "seq.h"
+#include "tun-metadata.h"
#include "unaligned.h"
#include "unixctl.h"
#include "util.h"
@@ -21,7 +21,6 @@
#include <stddef.h>
#include "compiler.h"
#include "dp-packet.h"
-#include "packets.h"
#include "unixctl.h"
struct netdev;
@@ -24,7 +24,6 @@
#include "openvswitch/list.h"
#include "ovs-numa.h"
#include "ovs-rcu.h"
-#include "packets.h"
#include "seq.h"
#include "openvswitch/shash.h"
#include "smap.h"
@@ -39,7 +39,6 @@
#include "openvswitch/dynamic-string.h"
#include "ovs-atomic.h"
#include "ovs-router.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "route-table.h"
#include "simap.h"
@@ -25,7 +25,6 @@
#include "fatal-signal.h"
#include "netdev-provider.h"
#include "openvswitch/ofpbuf.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "openvswitch/shash.h"
#include "svec.h"
@@ -45,7 +45,6 @@
#include "odp-netlink.h"
#include "openvswitch/json.h"
#include "openflow/openflow.h"
-#include "packets.h"
#include "openvswitch/ofp-print.h"
#include "openvswitch/poll-loop.h"
#include "seq.h"
@@ -21,7 +21,6 @@
#include "openvswitch/types.h"
#include "ovs-atomic.h"
#include "ovs-rcu.h"
-#include "packets.h"
#include "flow.h"
#ifdef __cplusplus
@@ -26,13 +26,13 @@
#include "openflow/nicira-ext.h"
#include "openvswitch/dynamic-string.h"
#include "openvswitch/meta-flow.h"
+#include "openvswitch/nsh.h"
#include "openvswitch/ofp-actions.h"
#include "openvswitch/ofp-errors.h"
#include "openvswitch/ofp-match.h"
#include "openvswitch/ofp-port.h"
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
#include "openvswitch/shash.h"
#include "tun-metadata.h"
#include "unaligned.h"
@@ -27,11 +27,11 @@
#include "csum.h"
#include "dp-packet.h"
#include "immintrin.h"
+#include "netlink.h"
#include "odp-execute.h"
#include "odp-execute-private.h"
#include "odp-netlink.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
VLOG_DEFINE_THIS_MODULE(odp_execute_avx512);
@@ -22,6 +22,7 @@
#include "cpu.h"
#include "dpdk.h"
#include "dp-packet.h"
+#include "netlink.h"
#include "odp-execute.h"
#include "odp-execute-private.h"
#include "odp-netlink.h"
@@ -32,7 +32,6 @@
#include "netlink.h"
#include "odp-netlink.h"
#include "odp-util.h"
-#include "packets.h"
#include "flow.h"
#include "unaligned.h"
#include "util.h"
@@ -33,8 +33,8 @@
#include "openvswitch/dynamic-string.h"
#include "flow.h"
#include "netlink.h"
+#include "openvswitch/nsh.h"
#include "openvswitch/ofpbuf.h"
-#include "packets.h"
#include "simap.h"
#include "timeval.h"
#include "tun-metadata.h"
@@ -32,6 +32,7 @@
struct ds;
struct nlattr;
+struct nsh_hdr;
struct ofpbuf;
struct simap;
struct pkt_metadata;
@@ -25,11 +25,13 @@
#include "openvswitch/ofp-ct.h"
#include "openflow/nicira-ext.h"
#include "openvswitch/dynamic-string.h"
+#include "net-proto.h"
#include "openvswitch/ofp-msgs.h"
#include "openvswitch/ofp-parse.h"
#include "openvswitch/ofp-errors.h"
#include "openvswitch/ofp-prop.h"
#include "openvswitch/ofp-util.h"
+#include "openvswitch/ofpbuf.h"
#include "openvswitch/packets.h"
#include "openvswitch/vlog.h"
@@ -22,8 +22,6 @@
#include "openvswitch/ofpbuf.h"
#include "openvswitch/ofp-parse.h"
#include "util.h"
-#include "lib/packets.h"
-
enum ofperr
decode_ed_prop(const struct ofp_ed_prop_header **ofp_prop,
@@ -17,12 +17,14 @@
#include <config.h>
#include "openvswitch/ofp-match.h"
#include "byte-order.h"
+#include "openvswitch/dynamic-string.h"
#include "flow.h"
#include "nx-match.h"
#include "openvswitch/match.h"
#include "openvswitch/ofp-errors.h"
#include "openvswitch/ofp-msgs.h"
#include "openvswitch/ofp-port.h"
+#include "openvswitch/ofpbuf.h"
#include "openvswitch/packets.h"
#include "openvswitch/vlog.h"
@@ -20,11 +20,11 @@
#include "byte-order.h"
#include "openvswitch/match.h"
#include "openvswitch/meta-flow.h"
+#include "net-proto.h"
#include "openvswitch/ofp-actions.h"
#include "openvswitch/ofp-flow.h"
#include "openvswitch/ofp-match.h"
#include "openvswitch/ofp-table.h"
-#include "packets.h"
#include "socket-util.h"
#include "util.h"
@@ -60,7 +60,6 @@
#include "openvswitch/ofp-util.h"
#include "openvswitch/ofpbuf.h"
#include "openvswitch/type-props.h"
-#include "packets.h"
#include "unaligned.h"
#include "util.h"
#include "uuid.h"
@@ -45,7 +45,6 @@
#include "openvswitch/type-props.h"
#include "openvswitch/vlog.h"
#include "openflow/intel-ext.h"
-#include "packets.h"
#include "random.h"
#include "tun-metadata.h"
#include "unaligned.h"
@@ -41,7 +41,6 @@
#include "lldp/lldpd-structs.h"
#include "netdev.h"
#include "openvswitch/types.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "smap.h"
#include "unixctl.h"
@@ -25,7 +25,6 @@
#include "openvswitch/list.h"
#include "lldp/lldpd.h"
#include "ovs-atomic.h"
-#include "packets.h"
#include "timer.h"
/* Transmit every LLDPD_TX_INTERVAL seconds. */
@@ -39,7 +39,6 @@
#include "openvswitch/dynamic-string.h"
#include "openvswitch/json.h"
#include "netdev.h"
-#include "packets.h"
#include "seq.h"
#include "ovs-thread.h"
#include "route-table.h"
deleted file mode 100644
@@ -1,1420 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-#include "packets.h"
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <stdlib.h>
-#include <netdb.h>
-#include "byte-order.h"
-#include "csum.h"
-#include "crc32c.h"
-#include "flow.h"
-#include "openvswitch/hmap.h"
-#include "openvswitch/dynamic-string.h"
-#include "ovs-thread.h"
-#include "odp-util.h"
-#include "dp-packet.h"
-#include "dp-packet-gso.h"
-#include "unaligned.h"
-
-struct in6_addr
-flow_tnl_dst(const struct flow_tnl *tnl)
-{
- return tnl->ip_dst ? in6_addr_mapped_ipv4(tnl->ip_dst) : tnl->ipv6_dst;
-}
-
-struct in6_addr
-flow_tnl_src(const struct flow_tnl *tnl)
-{
- return tnl->ip_src ? in6_addr_mapped_ipv4(tnl->ip_src) : tnl->ipv6_src;
-}
-
-/* Fills 'b' with a Reverse ARP packet with Ethernet source address 'eth_src'.
- * This function is used by Open vSwitch to compose packets in cases where
- * context is important but content doesn't (or shouldn't) matter.
- *
- * The returned packet has enough headroom to insert an 802.1Q VLAN header if
- * desired. */
-void
-compose_rarp(struct dp_packet *b, const struct eth_addr eth_src)
-{
- struct eth_header *eth;
- struct arp_eth_header *arp;
-
- dp_packet_clear(b);
- dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN
- + ARP_ETH_HEADER_LEN);
- dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
- eth = dp_packet_put_uninit(b, sizeof *eth);
- eth->eth_dst = eth_addr_broadcast;
- eth->eth_src = eth_src;
- eth->eth_type = htons(ETH_TYPE_RARP);
-
- arp = dp_packet_put_uninit(b, sizeof *arp);
- arp->ar_hrd = htons(ARP_HRD_ETHERNET);
- arp->ar_pro = htons(ARP_PRO_IP);
- arp->ar_hln = sizeof arp->ar_sha;
- arp->ar_pln = sizeof arp->ar_spa;
- arp->ar_op = htons(ARP_OP_RARP);
- arp->ar_sha = eth_src;
- put_16aligned_be32(&arp->ar_spa, htonl(0));
- arp->ar_tha = eth_src;
- put_16aligned_be32(&arp->ar_tpa, htonl(0));
-
- dp_packet_set_l3(b, arp);
- b->packet_type = htonl(PT_ETH);
-}
-
-/* Insert VLAN header according to given TCI. Packet passed must be Ethernet
- * packet. Ignores the CFI bit of 'tci' using 0 instead.
- *
- * Also adjusts the layer offsets accordingly. */
-void
-eth_push_vlan(struct dp_packet *packet, ovs_be16 tpid, ovs_be16 tci)
-{
- struct vlan_eth_header *veh;
-
- /* Insert new 802.1Q header. */
- veh = dp_packet_resize_l2(packet, VLAN_HEADER_LEN);
- memmove(veh, (char *)veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN);
- veh->veth_type = tpid;
- veh->veth_tci = tci & htons(~VLAN_CFI);
-}
-
-/* Removes outermost VLAN header (if any is present) from 'packet'.
- *
- * 'packet->l2_5' should initially point to 'packet''s outer-most VLAN header
- * or may be NULL if there are no VLAN headers. */
-void
-eth_pop_vlan(struct dp_packet *packet)
-{
- struct vlan_eth_header *veh = dp_packet_eth(packet);
-
- if (veh && dp_packet_size(packet) >= sizeof *veh
- && eth_type_vlan(veh->veth_type)) {
-
- memmove((char *)veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN);
- dp_packet_resize_l2(packet, -VLAN_HEADER_LEN);
- }
-}
-
-/* Push Ethernet header onto 'packet' assuming it is layer 3 */
-void
-push_eth(struct dp_packet *packet, const struct eth_addr *dst,
- const struct eth_addr *src)
-{
- struct eth_header *eh;
-
- ovs_assert(!dp_packet_is_eth(packet));
- eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);
- eh->eth_dst = *dst;
- eh->eth_src = *src;
- eh->eth_type = pt_ns_type_be(packet->packet_type);
- packet->packet_type = htonl(PT_ETH);
-}
-
-/* Removes Ethernet header, including VLAN header, from 'packet'.
- *
- * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */
-void
-pop_eth(struct dp_packet *packet)
-{
- char *l2_5 = dp_packet_l2_5(packet);
- char *l3 = dp_packet_l3(packet);
- ovs_be16 ethertype;
- int increment;
-
- ovs_assert(dp_packet_is_eth(packet));
- ovs_assert(l3 != NULL);
-
- if (l2_5) {
- increment = packet->l2_5_ofs;
- ethertype = *(ALIGNED_CAST(ovs_be16 *, (l2_5 - 2)));
- } else {
- increment = packet->l3_ofs;
- ethertype = *(ALIGNED_CAST(ovs_be16 *, (l3 - 2)));
- }
-
- dp_packet_resize_l2(packet, -increment);
- packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, ntohs(ethertype));
-}
-
-/* Set ethertype of the packet. */
-static void
-set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)
-{
- struct eth_header *eh = dp_packet_eth(packet);
-
- if (!eh) {
- return;
- }
-
- if (eth_type_vlan(eh->eth_type)) {
- ovs_be16 *p;
- char *l2_5 = dp_packet_l2_5(packet);
-
- p = ALIGNED_CAST(ovs_be16 *,
- (l2_5 ? l2_5 : (char *)dp_packet_l3(packet)) - 2);
- *p = eth_type;
- } else {
- eh->eth_type = eth_type;
- }
-}
-
-static bool is_mpls(struct dp_packet *packet)
-{
- return packet->l2_5_ofs != UINT16_MAX;
-}
-
-/* Set MPLS label stack entry to outermost MPLS header.*/
-void
-set_mpls_lse(struct dp_packet *packet, ovs_be32 mpls_lse)
-{
- /* Packet type should be MPLS to set label stack entry. */
- if (is_mpls(packet)) {
- struct mpls_hdr *mh = dp_packet_l2_5(packet);
-
- /* Update mpls label stack entry. */
- put_16aligned_be32(&mh->mpls_lse, mpls_lse);
- }
-}
-
-/* Push MPLS label stack entry 'lse' onto 'packet' as the outermost MPLS
- * header. If 'packet' does not already have any MPLS labels, then its
- * Ethertype is changed to 'ethtype' (which must be an MPLS Ethertype). */
-void
-push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse)
-{
- char * header;
- size_t len;
-
- if (!eth_type_mpls(ethtype)) {
- return;
- }
-
- if (!is_mpls(packet)) {
- /* Set MPLS label stack offset. */
- packet->l2_5_ofs = packet->l3_ofs;
- }
-
- set_ethertype(packet, ethtype);
-
- /* Push new MPLS shim header onto packet. */
- len = packet->l2_5_ofs;
- header = dp_packet_resize_l2_5(packet, MPLS_HLEN);
- memmove(header, header + MPLS_HLEN, len);
- memcpy(header + len, &lse, sizeof lse);
-
- pkt_metadata_init_conn(&packet->md);
-}
-
-void
-add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,
- bool l3_encap)
-{
- if (!eth_type_mpls(ethtype)) {
- return;
- }
-
- if (!l3_encap) {
- struct mpls_hdr *header = dp_packet_resize_l2(packet, MPLS_HLEN);
-
- put_16aligned_be32(&header->mpls_lse, lse);
- packet->l2_5_ofs = 0;
- packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,
- ntohs(ethtype));
- } else {
- size_t len;
- char *header;
-
- if (!is_mpls(packet)) {
- /* Set MPLS label stack offset. */
- packet->l2_5_ofs = packet->l3_ofs;
- }
- set_ethertype(packet, ethtype);
-
- /* Push new MPLS shim header onto packet. */
- len = packet->l2_5_ofs;
- header = dp_packet_resize_l2_5(packet, MPLS_HLEN);
- memmove(header, header + MPLS_HLEN, len);
- memcpy(header + len, &lse, sizeof lse);
- }
- pkt_metadata_init_conn(&packet->md);
-}
-
-/* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry.
- * If the label that was removed was the only MPLS label, changes 'packet''s
- * Ethertype to 'ethtype' (which ordinarily should not be an MPLS
- * Ethertype). */
-void
-pop_mpls(struct dp_packet *packet, ovs_be16 ethtype)
-{
- if (is_mpls(packet)) {
- struct mpls_hdr *mh = dp_packet_l2_5(packet);
- size_t len = packet->l2_5_ofs;
-
- set_ethertype(packet, ethtype);
- if (get_16aligned_be32(&mh->mpls_lse) & htonl(MPLS_BOS_MASK)) {
- dp_packet_set_l2_5(packet, NULL);
- }
- /* Shift the l2 header forward. */
- memmove((char*)dp_packet_data(packet) + MPLS_HLEN, dp_packet_data(packet), len);
- dp_packet_resize_l2_5(packet, -MPLS_HLEN);
-
- /* Invalidate offload flags as they are not valid after
- * decapsulation of MPLS header. */
- dp_packet_reset_offload(packet);
-
- /* packet_type must be reset for the MPLS packets with no l2 header */
- if (!len) {
- if (ethtype == htons(ETH_TYPE_TEB)) {
- /* The inner packet must be classified as ethernet if the
- * ethtype is ETH_TYPE_TEB. */
- packet->packet_type = htonl(PT_ETH);
- } else {
- packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,
- ntohs(ethtype));
- }
- }
- }
-}
-
-void
-push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src)
-{
- struct nsh_hdr *nsh;
- size_t length = nsh_hdr_len(nsh_hdr_src);
- uint8_t next_proto;
-
- switch (ntohl(packet->packet_type)) {
- case PT_ETH:
- next_proto = NSH_P_ETHERNET;
- break;
- case PT_IPV4:
- next_proto = NSH_P_IPV4;
- break;
- case PT_IPV6:
- next_proto = NSH_P_IPV6;
- break;
- case PT_NSH:
- next_proto = NSH_P_NSH;
- break;
- default:
- OVS_NOT_REACHED();
- }
-
- nsh = (struct nsh_hdr *) dp_packet_resize_l2(packet, length);
- memcpy(nsh, nsh_hdr_src, length);
- nsh->next_proto = next_proto;
- packet->packet_type = htonl(PT_NSH);
- dp_packet_reset_offsets(packet);
- packet->l3_ofs = 0;
-}
-
-bool
-pop_nsh(struct dp_packet *packet)
-{
- struct nsh_hdr *nsh = (struct nsh_hdr *) dp_packet_l3(packet);
- size_t length;
- uint32_t next_pt;
-
- if (packet->packet_type == htonl(PT_NSH) && nsh) {
- switch (nsh->next_proto) {
- case NSH_P_ETHERNET:
- next_pt = PT_ETH;
- break;
- case NSH_P_IPV4:
- next_pt = PT_IPV4;
- break;
- case NSH_P_IPV6:
- next_pt = PT_IPV6;
- break;
- case NSH_P_NSH:
- next_pt = PT_NSH;
- break;
- default:
- /* Unknown inner packet type. Drop packet. */
- return false;
- }
-
- length = nsh_hdr_len(nsh);
- dp_packet_reset_packet(packet, length);
- packet->packet_type = htonl(next_pt);
- /* Packet must be recirculated for further processing. */
- }
- return true;
-}
-
-/* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'. The
- * caller must free '*packetp'. On success, returns NULL. On failure, returns
- * an error message and stores NULL in '*packetp'.
- *
- * Aligns the L3 header of '*packetp' on a 32-bit boundary. */
-const char *
-eth_from_hex(const char *hex, struct dp_packet **packetp)
-{
- struct dp_packet *packet;
-
- /* Use 2 bytes of headroom to 32-bit align the L3 header. */
- packet = *packetp = dp_packet_new_with_headroom(strlen(hex) / 2, 2);
-
- if (dp_packet_put_hex(packet, hex, NULL)[0] != '\0') {
- dp_packet_delete(packet);
- *packetp = NULL;
- return "Trailing garbage in packet data";
- }
-
- if (dp_packet_size(packet) < ETH_HEADER_LEN) {
- dp_packet_delete(packet);
- *packetp = NULL;
- return "Packet data too short for Ethernet";
- }
-
- return NULL;
-}
-
-/* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',
- * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated
- * in 'b' and returned. This payload may be populated with appropriate
- * information by the caller. Sets 'b''s 'frame' pointer and 'l3' offset to
- * the Ethernet header and payload respectively. Aligns b->l3 on a 32-bit
- * boundary.
- *
- * The returned packet has enough headroom to insert an 802.1Q VLAN header if
- * desired. */
-void *
-eth_compose(struct dp_packet *b, const struct eth_addr eth_dst,
- const struct eth_addr eth_src, uint16_t eth_type,
- size_t size)
-{
- void *data;
- struct eth_header *eth;
-
-
- dp_packet_clear(b);
-
- /* The magic 2 here ensures that the L3 header (when it is added later)
- * will be 32-bit aligned. */
- dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size);
- dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
- eth = dp_packet_put_uninit(b, ETH_HEADER_LEN);
- data = dp_packet_put_zeros(b, size);
-
- eth->eth_dst = eth_dst;
- eth->eth_src = eth_src;
- eth->eth_type = htons(eth_type);
-
- b->packet_type = htonl(PT_ETH);
- dp_packet_set_l3(b, data);
-
- return data;
-}
-
-void
-packet_set_ipv4_addr(struct dp_packet *packet,
- ovs_16aligned_be32 *addr, ovs_be32 new_addr)
-{
- struct ip_header *nh = dp_packet_l3(packet);
- ovs_be32 old_addr = get_16aligned_be32(addr);
- size_t l4_size = dp_packet_l4_size(packet);
-
- pkt_metadata_init_conn(&packet->md);
-
- if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
- if (dp_packet_l4_checksum_valid(packet)) {
- dp_packet_l4_checksum_set_partial(packet);
- } else {
- struct tcp_header *th = dp_packet_l4(packet);
- th->tcp_csum = recalc_csum32(th->tcp_csum, old_addr, new_addr);
- }
- } else if (nh->ip_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN ) {
- if (dp_packet_l4_checksum_valid(packet)) {
- dp_packet_l4_checksum_set_partial(packet);
- } else {
- struct udp_header *uh = dp_packet_l4(packet);
- if (uh->udp_csum) {
- uh->udp_csum = recalc_csum32(uh->udp_csum, old_addr, new_addr);
- if (!uh->udp_csum) {
- uh->udp_csum = htons(0xffff);
- }
- }
- }
- }
-
- if (dp_packet_ip_checksum_valid(packet)) {
- dp_packet_ip_checksum_set_partial(packet);
- } else {
- nh->ip_csum = recalc_csum32(nh->ip_csum, old_addr, new_addr);
- }
- put_16aligned_be32(addr, new_addr);
-}
-
-/* Returns true, if packet contains at least one routing header where
- * segements_left > 0.
- *
- * This function assumes that L3 and L4 offsets are set in the packet. */
-bool
-packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr, bool *first_frag)
-{
- const struct ovs_16aligned_ip6_hdr *nh;
- size_t len;
- size_t remaining;
- uint8_t *data = dp_packet_l3(packet);
-
- remaining = packet->l4_ofs - packet->l3_ofs;
- if (remaining < sizeof *nh) {
- return false;
- }
- nh = ALIGNED_CAST(struct ovs_16aligned_ip6_hdr *, data);
- data += sizeof *nh;
- remaining -= sizeof *nh;
- *nexthdr = nh->ip6_nxt;
-
- while (1) {
- if ((*nexthdr != IPPROTO_HOPOPTS)
- && (*nexthdr != IPPROTO_ROUTING)
- && (*nexthdr != IPPROTO_DSTOPTS)
- && (*nexthdr != IPPROTO_AH)
- && (*nexthdr != IPPROTO_FRAGMENT)) {
- /* It's either a terminal header (e.g., TCP, UDP) or one we
- * don't understand. In either case, we're done with the
- * packet, so use it to fill in 'nw_proto'. */
- break;
- }
-
- /* We only verify that at least 8 bytes of the next header are
- * available, but many of these headers are longer. Ensure that
- * accesses within the extension header are within those first 8
- * bytes. All extension headers are required to be at least 8
- * bytes. */
- if (remaining < 8) {
- return false;
- }
-
- if (*nexthdr == IPPROTO_AH) {
- /* A standard AH definition isn't available, but the fields
- * we care about are in the same location as the generic
- * option header--only the header length is calculated
- * differently. */
- const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;
-
- *nexthdr = ext_hdr->ip6e_nxt;
- len = (ext_hdr->ip6e_len + 2) * 4;
- } else if (*nexthdr == IPPROTO_FRAGMENT) {
- const struct ovs_16aligned_ip6_frag *frag_hdr
- = ALIGNED_CAST(struct ovs_16aligned_ip6_frag *, data);
-
- *first_frag = !(frag_hdr->ip6f_offlg & IP6F_OFF_MASK) &&
- (frag_hdr->ip6f_offlg & IP6F_MORE_FRAG);
- *nexthdr = frag_hdr->ip6f_nxt;
- len = sizeof *frag_hdr;
- } else if (*nexthdr == IPPROTO_ROUTING) {
- const struct ip6_rthdr *rh = (struct ip6_rthdr *)data;
-
- if (rh->ip6r_segleft > 0) {
- return true;
- }
-
- *nexthdr = rh->ip6r_nxt;
- len = (rh->ip6r_len + 1) * 8;
- } else {
- const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;
-
- *nexthdr = ext_hdr->ip6e_nxt;
- len = (ext_hdr->ip6e_len + 1) * 8;
- }
-
- if (remaining < len) {
- return false;
- }
- remaining -= len;
- data += len;
- }
-
- return false;
-}
-
-static void
-packet_update_csum128(struct dp_packet *packet, uint8_t proto,
- ovs_16aligned_be32 addr[4],
- const struct in6_addr *new_addr)
-{
- size_t l4_size = dp_packet_l4_size(packet);
-
- if (proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
- if (dp_packet_l4_checksum_valid(packet)) {
- dp_packet_l4_checksum_set_partial(packet);
- } else {
- struct tcp_header *th = dp_packet_l4(packet);
-
- th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr);
- }
- } else if (proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
- if (dp_packet_l4_checksum_valid(packet)) {
- dp_packet_l4_checksum_set_partial(packet);
- } else {
- struct udp_header *uh = dp_packet_l4(packet);
-
- if (uh->udp_csum) {
- uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr);
- if (!uh->udp_csum) {
- uh->udp_csum = htons(0xffff);
- }
- }
- }
- } else if (proto == IPPROTO_ICMPV6 &&
- l4_size >= sizeof(struct icmp6_header)) {
- struct icmp6_header *icmp = dp_packet_l4(packet);
-
- icmp->icmp6_cksum = recalc_csum128(icmp->icmp6_cksum, addr, new_addr);
- }
-}
-
-void
-packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,
- ovs_16aligned_be32 addr[4],
- const struct in6_addr *new_addr,
- bool recalculate_csum)
-{
- if (recalculate_csum) {
- packet_update_csum128(packet, proto, addr, new_addr);
- }
- memcpy(addr, new_addr, sizeof(ovs_be32[4]));
- pkt_metadata_init_conn(&packet->md);
-}
-
-/* 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 dp_packet *packet, ovs_be32 src, ovs_be32 dst,
- uint8_t tos, uint8_t ttl)
-{
- struct ip_header *nh = dp_packet_l3(packet);
-
- if (get_16aligned_be32(&nh->ip_src) != src) {
- packet_set_ipv4_addr(packet, &nh->ip_src, src);
- }
-
- if (get_16aligned_be32(&nh->ip_dst) != dst) {
- packet_set_ipv4_addr(packet, &nh->ip_dst, dst);
- }
-
- if (nh->ip_tos != tos) {
- uint8_t *field = &nh->ip_tos;
-
- if (dp_packet_ip_checksum_valid(packet)) {
- dp_packet_ip_checksum_set_partial(packet);
- } else {
- 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;
-
- if (dp_packet_ip_checksum_valid(packet)) {
- dp_packet_ip_checksum_set_partial(packet);
- } else {
- nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),
- htons(ttl << 8));
- }
-
- *field = ttl;
- }
-}
-
-/* Modifies the IPv6 header fields of 'packet' to be consistent with 'src',
- * 'dst', 'traffic class', and 'next hop'. Updates 'packet''s L4 checksums as
- * appropriate. 'packet' must contain a valid IPv6 packet with correctly
- * populated l[34] offsets. */
-void
-packet_set_ipv6(struct dp_packet *packet, const struct in6_addr *src,
- const struct in6_addr *dst, uint8_t key_tc, ovs_be32 key_fl,
- uint8_t key_hl)
-{
- struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);
- bool recalc_csum = true;
- uint8_t proto = 0;
- bool rh_present;
-
- rh_present = packet_rh_present(packet, &proto, &recalc_csum);
-
- if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) {
- packet_set_ipv6_addr(packet, proto, nh->ip6_src.be32,
- src, recalc_csum);
- }
-
- if (memcmp(&nh->ip6_dst, dst, sizeof(ovs_be32[4]))) {
- packet_set_ipv6_addr(packet, proto, nh->ip6_dst.be32, dst,
- !rh_present && recalc_csum);
- }
-
- ip_set_ipv6_tc(&nh->ip6_flow, key_tc);
- ip_set_ipv6_flow_label(&nh->ip6_flow, key_fl);
- nh->ip6_hlim = key_hl;
-}
-
-static void
-packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)
-{
- if (*port != new_port) {
- if (csum) {
- *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 offset properly populated. */
-void
-packet_set_tcp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
-{
- struct tcp_header *th = dp_packet_l4(packet);
- ovs_be16 *csum = NULL;
-
- if (dp_packet_l4_checksum_valid(packet)) {
- dp_packet_l4_checksum_set_partial(packet);
- } else {
- csum = &th->tcp_csum;
- }
-
- packet_set_port(&th->tcp_src, src, csum);
- packet_set_port(&th->tcp_dst, dst, csum);
- pkt_metadata_init_conn(&packet->md);
-}
-
-/* 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 offset properly populated. */
-void
-packet_set_udp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
-{
- struct udp_header *uh = dp_packet_l4(packet);
-
- if (dp_packet_l4_checksum_valid(packet)) {
- dp_packet_l4_checksum_set_partial(packet);
- packet_set_port(&uh->udp_src, src, NULL);
- packet_set_port(&uh->udp_dst, dst, NULL);
- } else {
- ovs_be16 *csum = uh->udp_csum ? &uh->udp_csum : NULL;
-
- packet_set_port(&uh->udp_src, src, csum);
- packet_set_port(&uh->udp_dst, dst, csum);
-
- if (csum && !uh->udp_csum) {
- uh->udp_csum = htons(0xffff);
- }
- }
-
- pkt_metadata_init_conn(&packet->md);
-}
-
-/* Sets the SCTP source and destination port ('src' and 'dst' respectively) of
- * the SCTP header contained in 'packet'. 'packet' must be a valid SCTP packet
- * with its l4 offset properly populated. */
-void
-packet_set_sctp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
-{
- struct sctp_header *sh = dp_packet_l4(packet);
-
- if (dp_packet_l4_checksum_valid(packet)) {
- dp_packet_l4_checksum_set_partial(packet);
- sh->sctp_src = src;
- sh->sctp_dst = dst;
- } else {
- ovs_be32 old_csum, old_correct_csum, new_csum;
- uint16_t tp_len = dp_packet_l4_size(packet);
-
- old_csum = get_16aligned_be32(&sh->sctp_csum);
- put_16aligned_be32(&sh->sctp_csum, 0);
- old_correct_csum = crc32c((void *) sh, tp_len);
-
- sh->sctp_src = src;
- sh->sctp_dst = dst;
-
- new_csum = crc32c((void *) sh, tp_len);
- put_16aligned_be32(&sh->sctp_csum, old_csum ^ old_correct_csum
- ^ new_csum);
- }
-
- pkt_metadata_init_conn(&packet->md);
-}
-
-/* Sets the ICMP type and code of the ICMP header contained in 'packet'.
- * 'packet' must be a valid ICMP packet with its l4 offset properly
- * populated. */
-void
-packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code)
-{
- struct icmp_header *ih = dp_packet_l4(packet);
- ovs_be16 orig_tc = htons(ih->icmp_type << 8 | ih->icmp_code);
- ovs_be16 new_tc = htons(type << 8 | code);
-
- if (orig_tc != new_tc) {
- ih->icmp_type = type;
- ih->icmp_code = code;
-
- ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_tc, new_tc);
- }
- pkt_metadata_init_conn(&packet->md);
-}
-
-/* Sets the IGMP type to IGMP_HOST_MEMBERSHIP_QUERY and populates the
- * v3 query header fields in 'packet'. 'packet' must be a valid IGMPv3
- * query packet with its l4 offset properly populated.
- */
-void
-packet_set_igmp3_query(struct dp_packet *packet, uint8_t max_resp,
- ovs_be32 group, bool srs, uint8_t qrv, uint8_t qqic)
-{
- struct igmpv3_query_header *igh = dp_packet_l4(packet);
- ovs_be16 orig_type_max_resp =
- htons(igh->type << 8 | igh->max_resp);
- ovs_be16 new_type_max_resp =
- htons(IGMP_HOST_MEMBERSHIP_QUERY << 8 | max_resp);
-
- if (orig_type_max_resp != new_type_max_resp) {
- igh->type = IGMP_HOST_MEMBERSHIP_QUERY;
- igh->max_resp = max_resp;
- igh->csum = recalc_csum16(igh->csum, orig_type_max_resp,
- new_type_max_resp);
- }
-
- ovs_be32 old_group = get_16aligned_be32(&igh->group);
-
- if (old_group != group) {
- put_16aligned_be32(&igh->group, group);
- igh->csum = recalc_csum32(igh->csum, old_group, group);
- }
-
- /* See RFC 3376 4.1.6. */
- if (qrv > 7) {
- qrv = 0;
- }
-
- ovs_be16 orig_srs_qrv_qqic = htons(igh->srs_qrv << 8 | igh->qqic);
- ovs_be16 new_srs_qrv_qqic = htons(srs << 11 | qrv << 8 | qqic);
-
- if (orig_srs_qrv_qqic != new_srs_qrv_qqic) {
- igh->srs_qrv = (srs << 3 | qrv);
- igh->qqic = qqic;
- igh->csum = recalc_csum16(igh->csum, orig_srs_qrv_qqic,
- new_srs_qrv_qqic);
- }
-}
-
-void
-packet_set_nd_ext(struct dp_packet *packet, const ovs_16aligned_be32 rso_flags,
- const uint8_t opt_type)
-{
- struct ovs_nd_msg *ns;
- struct ovs_nd_lla_opt *opt;
- int bytes_remain = dp_packet_l4_size(packet);
- struct ovs_16aligned_ip6_hdr * nh = dp_packet_l3(packet);
- uint32_t pseudo_hdr_csum = 0;
-
- if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {
- return;
- }
-
- if (nh) {
- pseudo_hdr_csum = ip_csum_pseudoheader6(nh);
- }
-
- ns = dp_packet_l4(packet);
- opt = &ns->options[0];
-
- /* set RSO flags and option type */
- ns->rso_flags = rso_flags;
- opt->type = opt_type;
-
- /* recalculate checksum */
- ovs_be16 *csum_value = &(ns->icmph.icmp6_cksum);
- *csum_value = 0;
- *csum_value = csum_finish(csum_continue(pseudo_hdr_csum,
- &(ns->icmph), bytes_remain));
-
-}
-
-void
-packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,
- const struct eth_addr sll, const struct eth_addr tll)
-{
- struct ovs_nd_msg *ns;
- struct ovs_nd_lla_opt *opt;
- int bytes_remain = dp_packet_l4_size(packet);
-
- if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {
- return;
- }
-
- ns = dp_packet_l4(packet);
- opt = &ns->options[0];
- bytes_remain -= sizeof(*ns);
-
- if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) {
- packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, ns->target.be32, target,
- true);
- }
-
- while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0
- && bytes_remain >= (opt->len * ND_LLA_OPT_LEN)) {
- if (opt->type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) {
- if (!eth_addr_equals(opt->mac, sll)) {
- ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
-
- *csum = recalc_csum48(*csum, opt->mac, sll);
- opt->mac = sll;
- }
-
- /* A packet can only contain one SLL or TLL option */
- break;
- } else if (opt->type == ND_OPT_TARGET_LINKADDR && opt->len == 1) {
- if (!eth_addr_equals(opt->mac, tll)) {
- ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
-
- *csum = recalc_csum48(*csum, opt->mac, tll);
- opt->mac = tll;
- }
-
- /* A packet can only contain one SLL or TLL option */
- break;
- }
-
- opt += opt->len;
- bytes_remain -= opt->len * ND_LLA_OPT_LEN;
- }
-}
-
-#define ARP_PACKET_SIZE (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \
- ARP_ETH_HEADER_LEN)
-
-/* Clears 'b' and replaces its contents by an ARP frame with the specified
- * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'. The outer
- * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination
- * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if
- * 'broadcast' is true. Points the L3 header to the ARP header. */
-void
-compose_arp(struct dp_packet *b, uint16_t arp_op,
- const struct eth_addr arp_sha, const struct eth_addr arp_tha,
- bool broadcast, ovs_be32 arp_spa, ovs_be32 arp_tpa)
-{
- compose_arp__(b);
-
- struct eth_header *eth = dp_packet_eth(b);
- eth->eth_dst = broadcast ? eth_addr_broadcast : arp_tha;
- eth->eth_src = arp_sha;
-
- struct arp_eth_header *arp = dp_packet_l3(b);
- arp->ar_op = htons(arp_op);
- arp->ar_sha = arp_sha;
- arp->ar_tha = arp_tha;
- put_16aligned_be32(&arp->ar_spa, arp_spa);
- put_16aligned_be32(&arp->ar_tpa, arp_tpa);
-}
-
-/* Clears 'b' and replaces its contents by an ARP frame. Sets the fields in
- * the Ethernet and ARP headers that are fixed for ARP frames to those fixed
- * values, and zeroes the other fields. Points the L3 header to the ARP
- * header. */
-void
-compose_arp__(struct dp_packet *b)
-{
- dp_packet_clear(b);
- dp_packet_prealloc_tailroom(b, ARP_PACKET_SIZE);
- dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
-
- struct eth_header *eth = dp_packet_put_zeros(b, sizeof *eth);
- eth->eth_type = htons(ETH_TYPE_ARP);
-
- struct arp_eth_header *arp = dp_packet_put_zeros(b, sizeof *arp);
- arp->ar_hrd = htons(ARP_HRD_ETHERNET);
- arp->ar_pro = htons(ARP_PRO_IP);
- arp->ar_hln = sizeof arp->ar_sha;
- arp->ar_pln = sizeof arp->ar_spa;
-
- dp_packet_set_l3(b, arp);
-
- b->packet_type = htonl(PT_ETH);
-}
-
-/* This function expects packet with ethernet header with correct
- * l3 pointer set. */
-void *
-compose_ipv6(struct dp_packet *packet, uint8_t proto,
- const struct in6_addr *src, const struct in6_addr *dst,
- uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size)
-{
- struct ovs_16aligned_ip6_hdr *nh;
- void *data;
-
- nh = dp_packet_l3(packet);
- nh->ip6_vfc = 0x60;
- nh->ip6_nxt = proto;
- nh->ip6_plen = htons(size);
- data = dp_packet_put_zeros(packet, size);
- dp_packet_set_l4(packet, data);
- packet_set_ipv6(packet, src, dst, key_tc, key_fl, key_hl);
- return data;
-}
-
-/* Compose an IPv6 Neighbor Discovery Neighbor Solicitation message. */
-void
-compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src,
- const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst)
-{
- struct in6_addr sn_addr;
- struct eth_addr eth_dst;
- struct ovs_nd_msg *ns;
- struct ovs_nd_lla_opt *lla_opt;
- uint32_t icmp_csum;
-
- in6_addr_solicited_node(&sn_addr, ipv6_dst);
- ipv6_multicast_to_ethernet(ð_dst, &sn_addr);
-
- eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
- ns = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, &sn_addr,
- 0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);
-
- ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
- ns->icmph.icmp6_code = 0;
- put_16aligned_be32(&ns->rso_flags, htonl(0));
-
- lla_opt = &ns->options[0];
- lla_opt->type = ND_OPT_SOURCE_LINKADDR;
- lla_opt->len = 1;
-
- packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero);
-
- ns->icmph.icmp6_cksum = 0;
- icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
- ns->icmph.icmp6_cksum = csum_finish(
- csum_continue(icmp_csum, ns, ND_MSG_LEN + ND_LLA_OPT_LEN));
-}
-
-/* Compose an IPv6 Neighbor Discovery Neighbor Advertisement message. */
-void
-compose_nd_na(struct dp_packet *b,
- const struct eth_addr eth_src, const struct eth_addr eth_dst,
- const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,
- ovs_be32 rso_flags)
-{
- struct ovs_nd_msg *na;
- struct ovs_nd_lla_opt *lla_opt;
- uint32_t icmp_csum;
-
- eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
- na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst,
- 0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);
-
- na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;
- na->icmph.icmp6_code = 0;
- put_16aligned_be32(&na->rso_flags, rso_flags);
-
- lla_opt = &na->options[0];
- lla_opt->type = ND_OPT_TARGET_LINKADDR;
- lla_opt->len = 1;
-
- packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src);
-
- na->icmph.icmp6_cksum = 0;
- icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
- na->icmph.icmp6_cksum = csum_finish(csum_continue(
- icmp_csum, na, ND_MSG_LEN + ND_LLA_OPT_LEN));
-}
-
-/* Compose an IPv6 Neighbor Discovery Router Advertisement message with
- * Source Link-layer Address Option and MTU Option.
- * Caller can call packet_put_ra_prefix_opt to append Prefix Information
- * Options to composed messags in 'b'. */
-void
-compose_nd_ra(struct dp_packet *b,
- const struct eth_addr eth_src, const struct eth_addr eth_dst,
- const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,
- uint8_t cur_hop_limit, uint8_t mo_flags,
- ovs_be16 router_lt, ovs_be32 reachable_time,
- ovs_be32 retrans_timer, uint32_t mtu)
-{
- /* Don't compose Router Advertisement packet with MTU Option if mtu
- * value is 0. */
- bool with_mtu = mtu != 0;
- size_t mtu_opt_len = with_mtu ? ND_MTU_OPT_LEN : 0;
-
- eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
-
- struct ovs_ra_msg *ra = compose_ipv6(
- b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255,
- RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len);
- ra->icmph.icmp6_type = ND_ROUTER_ADVERT;
- ra->icmph.icmp6_code = 0;
- ra->cur_hop_limit = cur_hop_limit;
- ra->mo_flags = mo_flags;
- ra->router_lifetime = router_lt;
- ra->reachable_time = reachable_time;
- ra->retrans_timer = retrans_timer;
-
- struct ovs_nd_lla_opt *lla_opt = ra->options;
- lla_opt->type = ND_OPT_SOURCE_LINKADDR;
- lla_opt->len = 1;
- lla_opt->mac = eth_src;
-
- if (with_mtu) {
- /* ovs_nd_mtu_opt has the same size with ovs_nd_lla_opt. */
- struct ovs_nd_mtu_opt *mtu_opt
- = (struct ovs_nd_mtu_opt *)(lla_opt + 1);
- mtu_opt->type = ND_OPT_MTU;
- mtu_opt->len = 1;
- mtu_opt->reserved = 0;
- put_16aligned_be32(&mtu_opt->mtu, htonl(mtu));
- }
-
- ra->icmph.icmp6_cksum = 0;
- uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
- ra->icmph.icmp6_cksum = csum_finish(csum_continue(
- icmp_csum, ra, RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len));
-}
-
-/* Append an IPv6 Neighbor Discovery Prefix Information option to a
- * Router Advertisement message. */
-void
-packet_put_ra_prefix_opt(struct dp_packet *b,
- uint8_t plen, uint8_t la_flags,
- ovs_be32 valid_lifetime, ovs_be32 preferred_lifetime,
- const ovs_be128 prefix)
-{
- size_t prev_l4_size = dp_packet_l4_size(b);
- struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(b);
- nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN);
-
- struct ovs_nd_prefix_opt *prefix_opt =
- dp_packet_put_uninit(b, sizeof *prefix_opt);
- prefix_opt->type = ND_OPT_PREFIX_INFORMATION;
- prefix_opt->len = 4;
- prefix_opt->prefix_len = plen;
- prefix_opt->la_flags = la_flags;
- put_16aligned_be32(&prefix_opt->valid_lifetime, valid_lifetime);
- put_16aligned_be32(&prefix_opt->preferred_lifetime, preferred_lifetime);
- put_16aligned_be32(&prefix_opt->reserved, 0);
- memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4]));
-
- struct ovs_ra_msg *ra = dp_packet_l4(b);
- ra->icmph.icmp6_cksum = 0;
- uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));
- ra->icmph.icmp6_cksum = csum_finish(csum_continue(
- icmp_csum, ra, prev_l4_size + ND_PREFIX_OPT_LEN));
-}
-
-void
-IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6)
-{
- if (is_ipv6) {
- ovs_16aligned_be32 *ip6 = dp_packet_l3(pkt);
-
- put_16aligned_be32(ip6, get_16aligned_be32(ip6) |
- htonl(IP_ECN_CE << 20));
- } else {
- struct ip_header *nh = dp_packet_l3(pkt);
- uint8_t tos = nh->ip_tos;
-
- tos |= IP_ECN_CE;
- if (nh->ip_tos != tos) {
- if (dp_packet_ip_checksum_valid(pkt)) {
- dp_packet_ip_checksum_set_partial(pkt);
- } else {
- nh->ip_csum = recalc_csum16(nh->ip_csum, htons(nh->ip_tos),
- htons((uint16_t) tos));
- }
-
- nh->ip_tos = tos;
- }
- }
-}
-
-/* Set TCP checksum field in packet 'p' with complete checksum.
- * The packet must have the L3 and L4 offsets. */
-void
-packet_tcp_complete_csum(struct dp_packet *p, bool inner)
-{
- struct tcp_header *tcp;
- size_t tcp_sz;
- void *ip_hdr;
-
- if (inner) {
- tcp = dp_packet_inner_l4(p);
- ip_hdr = dp_packet_inner_l3(p);
- tcp_sz = dp_packet_inner_l4_size(p);
- } else {
- tcp = dp_packet_l4(p);
- ip_hdr = dp_packet_l3(p);
- tcp_sz = dp_packet_l4_size(p);
- }
-
- ovs_assert(tcp);
- ovs_assert(ip_hdr);
-
- tcp->tcp_csum = 0;
- if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {
- struct ip_header *ip = ip_hdr;
-
- tcp->tcp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),
- tcp, tcp_sz));
- } else {
- struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;
-
- tcp->tcp_csum = ip_csum_upperlayer6(ip6, tcp, ip6->ip6_nxt,
- tcp_sz);
- }
-
- if (inner) {
- dp_packet_inner_l4_checksum_set_good(p);
- } else {
- dp_packet_l4_checksum_set_good(p);
- }
-}
-
-/* Set UDP checksum field in packet 'p' with complete checksum.
- * The packet must have the L3 and L4 offsets. */
-void
-packet_udp_complete_csum(struct dp_packet *p, bool inner)
-{
- struct udp_header *udp;
- size_t udp_sz;
- void *ip_hdr;
-
- if (inner) {
- udp = dp_packet_inner_l4(p);
- ip_hdr = dp_packet_inner_l3(p);
- udp_sz = dp_packet_inner_l4_size(p);
- } else {
- udp = dp_packet_l4(p);
- ip_hdr = dp_packet_l3(p);
- udp_sz = dp_packet_l4_size(p);
- }
-
- ovs_assert(udp);
- ovs_assert(ip_hdr);
-
- /* Skip csum calculation if the udp_csum is zero. */
- if (!udp->udp_csum) {
- goto out;
- }
-
- udp->udp_csum = 0;
- if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {
- struct ip_header *ip = ip_hdr;
-
- udp->udp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),
- udp, udp_sz));
- } else {
- struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;
-
- udp->udp_csum = ip_csum_upperlayer6(ip6, udp, ip6->ip6_nxt,
- udp_sz);
- }
-
- if (!udp->udp_csum) {
- udp->udp_csum = htons(0xffff);
- }
-
-out:
- if (inner) {
- dp_packet_inner_l4_checksum_set_good(p);
- } else {
- dp_packet_l4_checksum_set_good(p);
- }
-}
-
-/* This helper computes a "constant" UDP checksum without looking at the
- * L4 payload.
- *
- * This is possible when L4 is either TCP or UDP: the L4 payload checksum
- * is either computed in SW or in HW later, but its contribution to the
- * outer checksum is cancelled by the L4 payload being part of the global
- * packet sum. */
-bool
-packet_udp_tunnel_csum(struct dp_packet *p)
-{
- struct ip_header *inner_ip;
- const void *inner_l4_data;
- char *after_inner_l4_csum;
- size_t inner_l4_csum_off;
- struct udp_header *udp;
- ovs_be16 inner_l4_csum;
- uint32_t partial_csum;
- struct ip_header *ip;
- uint32_t inner_csum;
- uint16_t tso_segsz;
- bool inner_ipv4;
- void *inner_l4;
-
- inner_ip = dp_packet_inner_l3(p);
- inner_l4 = dp_packet_inner_l4(p);
- ip = dp_packet_l3(p);
- udp = dp_packet_l4(p);
-
- if (dp_packet_inner_l4_proto_tcp(p)) {
- inner_l4_csum_off = offsetof(struct tcp_header, tcp_csum);
- inner_l4_data = dp_packet_get_inner_tcp_payload(p);
- if (!inner_l4_data) {
- /* Malformed packet. */
- return false;
- }
- } else if (dp_packet_inner_l4_proto_udp(p)) {
- inner_l4_csum_off = offsetof(struct udp_header, udp_csum);
- inner_l4_data = (char *) inner_l4 + sizeof (struct udp_header);
- if (((struct udp_header *) inner_l4)->udp_csum == 0) {
- /* There is no nested checksum.
- * No choice but compute a full checksum. */
- return false;
- }
- } else {
- /* This optimisation applies only to inner TCP/UDP. */
- return false;
- }
-
- if (!dp_packet_inner_l4_checksum_valid(p)) {
- /* We have no idea about the contribution of the payload data
- * and what the L4 checksum put in the packet data looks like.
- * Simpler is to let a full checksum happen. */
- return false;
- }
-
- inner_ipv4 = IP_VER(inner_ip->ip_ihl_ver) == 4;
- if (inner_ipv4) {
- inner_csum = ip_csum_pseudoheader(inner_ip);
- } else {
- struct ovs_16aligned_ip6_hdr *inner_ip6 = dp_packet_inner_l3(p);
-
- inner_csum = ip_csum_pseudoheader6(inner_ip6);
- }
-
- inner_csum = csum_continue(inner_csum, inner_l4, inner_l4_csum_off);
- after_inner_l4_csum = (char *) inner_l4 + inner_l4_csum_off + 2;
- inner_l4_csum = csum_finish(csum_continue(inner_csum, after_inner_l4_csum,
- (char *) inner_l4_data - after_inner_l4_csum));
- /* Important: for inner UDP, a null inner_l4_csum here should in theory be
- * replaced with 0xffff. However, since the only use of inner_l4_csum is
- * for the final outer checksum with a csum_add16() below, we can skip this
- * entirely because adding 0xffff will have the same effect as adding 0x0
- * after reducing in csum_finish. */
-
- udp->udp_csum = 0;
- if (IP_VER(ip->ip_ihl_ver) == 4) {
- partial_csum = ip_csum_pseudoheader(ip);
- } else {
- struct ovs_16aligned_ip6_hdr *ip6 = dp_packet_l3(p);
-
- partial_csum = ip_csum_pseudoheader6(ip6);
- }
-
- partial_csum = csum_continue(partial_csum, udp,
- (char *) inner_ip - (char *) udp);
- if (!inner_ipv4 || !dp_packet_inner_ip_checksum_valid(p)) {
- /* IPv6 has no checksum, so for inner IPv6, we need to sum the header.
- *
- * In IPv4 case, if inner checksum is already good or HW offload
- * has been requested, the (final) sum of the IPv4 header will be 0.
- * Otherwise, we need to sum the header like for IPv6. */
- partial_csum = csum_continue(partial_csum, inner_ip,
- (char *) inner_l4 - (char *) inner_ip);
- }
- partial_csum = csum_continue(partial_csum, inner_l4, inner_l4_csum_off);
- partial_csum = csum_add16(partial_csum, inner_l4_csum);
- partial_csum = csum_continue(partial_csum, after_inner_l4_csum,
- (char *) inner_l4_data - after_inner_l4_csum);
- udp->udp_csum = csum_finish(partial_csum);
- tso_segsz = dp_packet_get_tso_segsz(p);
- if (tso_segsz) {
- uint16_t payload_len = dp_packet_get_inner_tcp_payload_length(p);
-
- ovs_assert(payload_len == tso_segsz * dp_packet_gso_nr_segs(p));
-
- /* The pseudo header used in the outer UDP checksum is dependent on
- * the ip_tot_len / ip6_plen which was a reflection of the TSO frame
- * size. The segmented packet will be shorter. */
- udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),
- htons(tso_segsz));
-
- /* When segmenting the packet, various headers get updated:
- * - inner L3
- * - for IPv4, ip_tot_len is updated, BUT it is not affecting the
- * outer UDP checksum because the IPv4 header itself contains
- * a checksum that compensates for this update,
- * - for IPv6, ip6_plen is updated, and this must be considered,
- * - inner L4
- * - inner pseudo header used in the TCP checksum is dependent on
- * the inner ip_tot_len / ip6_plen,
- * - TCP seq number is updated,
- * - the HW may change some TCP flags (think PSH/FIN),
- * BUT the TCP checksum will compensate for those updates,
- *
- * Summary: we only care about the inner IPv6 header update.
- */
- if (IP_VER(inner_ip->ip_ihl_ver) != 4) {
- udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),
- htons(tso_segsz));
- }
- }
- if (!udp->udp_csum) {
- udp->udp_csum = htons(0xffff);
- }
- dp_packet_l4_checksum_set_good(p);
-
- return true;
-}
-
-/* Set SCTP checksum field in packet 'p' with complete checksum.
- * The packet must have the L3 and L4 offsets. */
-void
-packet_sctp_complete_csum(struct dp_packet *p, bool inner)
-{
- struct sctp_header *sh;
- uint16_t tp_len;
- ovs_be32 csum;
-
- if (inner) {
- sh = dp_packet_inner_l4(p);
- tp_len = dp_packet_inner_l4_size(p);
- } else {
- sh = dp_packet_l4(p);
- tp_len = dp_packet_l4_size(p);
- }
-
- ovs_assert(sh);
-
- put_16aligned_be32(&sh->sctp_csum, 0);
- csum = crc32c((void *) sh, tp_len);
- put_16aligned_be32(&sh->sctp_csum, csum);
-
- if (inner) {
- dp_packet_inner_l4_checksum_set_good(p);
- } else {
- dp_packet_l4_checksum_set_good(p);
- }
-}
deleted file mode 100644
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PACKETS_H
-#define PACKETS_H 1
-
-#include <inttypes.h>
-#include <sys/types.h>
-#include <stdint.h>
-#include <string.h>
-#include "compiler.h"
-#include "openvswitch/geneve.h"
-#include "openvswitch/packets.h"
-#include "openvswitch/types.h"
-#include "net-proto.h"
-#include "openvswitch/nsh.h"
-#include "odp-netlink.h"
-#include "random.h"
-#include "hash.h"
-#include "tun-metadata.h"
-#include "unaligned.h"
-#include "util.h"
-#include "timeval.h"
-
-struct dp_packet;
-struct conn;
-struct ds;
-
-/* Purely internal to OVS userspace. These flags should never be exposed to
- * the outside world and so aren't included in the flags mask. */
-
-/* Tunnel information is in userspace datapath format. */
-#define FLOW_TNL_F_UDPIF (1 << 4)
-
-static inline bool
-flow_tnl_dst_is_set(const struct flow_tnl *tnl)
-{
- return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst);
-}
-
-static inline bool
-flow_tnl_src_is_set(const struct flow_tnl *tnl)
-{
- return tnl->ip_src || ipv6_addr_is_set(&tnl->ipv6_src);
-}
-
-struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl);
-struct in6_addr flow_tnl_src(const struct flow_tnl *tnl);
-
-/* Returns an offset to 'src' covering all the meaningful fields in 'src'. */
-static inline size_t
-flow_tnl_size(const struct flow_tnl *src)
-{
- if (!flow_tnl_dst_is_set(src)) {
- /* Covers ip_dst and ipv6_dst only. */
- return offsetof(struct flow_tnl, ip_src);
- }
- if (src->flags & FLOW_TNL_F_UDPIF) {
- /* Datapath format, cover all options we have. */
- return offsetof(struct flow_tnl, metadata.opts)
- + src->metadata.present.len;
- }
- if (!src->metadata.present.map) {
- /* No TLVs, opts is irrelevant. */
- return offsetof(struct flow_tnl, metadata.opts);
- }
- /* Have decoded TLVs, opts is relevant. */
- return sizeof *src;
-}
-
-/* Copy flow_tnl, but avoid copying unused portions of tun_metadata. Unused
- * data in 'dst' is NOT cleared, so this must not be used in cases where the
- * uninitialized portion may be hashed over. */
-static inline void
-flow_tnl_copy__(struct flow_tnl *dst, const struct flow_tnl *src)
-{
- memcpy(dst, src, flow_tnl_size(src));
-}
-
-/* Datapath packet metadata */
-struct pkt_metadata {
-PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,
- uint32_t recirc_id; /* Recirculation id carried with the
- recirculating packets. 0 for packets
- received from the wire. */
- uint32_t dp_hash; /* hash value computed by the recirculation
- action. */
- uint32_t skb_priority; /* Packet priority for QoS. */
- uint32_t pkt_mark; /* Packet mark. */
- uint8_t ct_state; /* Connection state. */
- bool ct_orig_tuple_ipv6;
- uint16_t ct_zone; /* Connection zone. */
- uint32_t ct_mark; /* Connection mark. */
- ovs_u128 ct_label; /* Connection label. */
- union flow_in_port in_port; /* Input port. */
- odp_port_t orig_in_port; /* Originating in_port for tunneled packets */
- struct conn *conn; /* Cached conntrack connection. */
- bool reply; /* True if reply direction. */
- bool icmp_related; /* True if ICMP related. */
-);
-
-PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline1,
- union { /* Populated only for non-zero 'ct_state'. */
- struct ovs_key_ct_tuple_ipv4 ipv4;
- struct ovs_key_ct_tuple_ipv6 ipv6; /* Used only if */
- } ct_orig_tuple; /* 'ct_orig_tuple_ipv6' is set */
-);
-
-PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline2,
- struct flow_tnl tunnel; /* Encapsulating tunnel parameters. Note that
- * if 'ip_dst' == 0, the rest of the fields may
- * be uninitialized. */
-);
-};
-
-BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline0) == 0);
-BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline1) ==
- CACHE_LINE_SIZE);
-BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline2) ==
- 2 * CACHE_LINE_SIZE);
-
-static inline void
-pkt_metadata_init_tnl(struct pkt_metadata *md)
-{
- odp_port_t orig_in_port;
-
- /* Zero up through the tunnel metadata options. The length and table
- * are before this and as long as they are empty, the options won't
- * be looked at. Keep the orig_in_port field. */
- orig_in_port = md->in_port.odp_port;
- memset(md, 0, offsetof(struct pkt_metadata, tunnel.metadata.opts));
- md->orig_in_port = orig_in_port;
-}
-
-static inline void
-pkt_metadata_init_conn(struct pkt_metadata *md)
-{
- md->conn = NULL;
-}
-
-static inline void
-pkt_metadata_init(struct pkt_metadata *md, odp_port_t port)
-{
- /* This is called for every packet in userspace datapath and affects
- * performance if all the metadata is initialized. Hence, fields should
- * only be zeroed out when necessary.
- *
- * Initialize only till ct_state. Once the ct_state is zeroed out rest
- * of ct fields will not be looked at unless ct_state != 0.
- */
- memset(md, 0, offsetof(struct pkt_metadata, ct_orig_tuple_ipv6));
-
- /* It can be expensive to zero out all of the tunnel metadata. However,
- * we can just zero out ip_dst and the rest of the data will never be
- * looked at. */
- md->tunnel.ip_dst = 0;
- md->tunnel.ipv6_dst = in6addr_any;
- md->in_port.odp_port = port;
- md->orig_in_port = port;
- md->conn = NULL;
-}
-
-/* This function prefetches the cachelines touched by pkt_metadata_init()
- * and pkt_metadata_init_tnl(). For performance reasons the two functions
- * should be kept in sync. */
-static inline void
-pkt_metadata_prefetch_init(struct pkt_metadata *md)
-{
- /* Prefetch cacheline0 as members till ct_state and odp_port will
- * be initialized later in pkt_metadata_init(). */
- OVS_PREFETCH(md->cacheline0);
-
- /* Prefetch cacheline1 as members of this cacheline will be zeroed out
- * in pkt_metadata_init_tnl(). */
- OVS_PREFETCH(md->cacheline1);
-
- /* Prefetch cachline2 as ip_dst & ipv6_dst fields will be initialized. */
- OVS_PREFETCH(md->cacheline2);
-}
-
-void compose_rarp(struct dp_packet *, const struct eth_addr);
-
-void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci);
-void eth_pop_vlan(struct dp_packet *);
-
-const char *eth_from_hex(const char *hex, struct dp_packet **packetp);
-
-void set_mpls_lse(struct dp_packet *, ovs_be32 label);
-void push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse);
-void pop_mpls(struct dp_packet *, ovs_be16 ethtype);
-void add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,
- bool l3_encap);
-
-
-void push_eth(struct dp_packet *packet, const struct eth_addr *dst,
- const struct eth_addr *src);
-void pop_eth(struct dp_packet *packet);
-
-void push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src);
-bool pop_nsh(struct dp_packet *packet);
-
-void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst,
- const struct eth_addr eth_src, uint16_t eth_type,
- size_t size);
-void *snap_compose(struct dp_packet *, const struct eth_addr eth_dst,
- const struct eth_addr eth_src,
- unsigned int oui, uint16_t snap_type, size_t size);
-void packet_set_ipv4(struct dp_packet *, ovs_be32 src, ovs_be32 dst, uint8_t tos,
- uint8_t ttl);
-void packet_set_ipv4_addr(struct dp_packet *packet, ovs_16aligned_be32 *addr,
- ovs_be32 new_addr);
-void packet_set_ipv6(struct dp_packet *, const struct in6_addr *src,
- const struct in6_addr *dst, uint8_t tc,
- ovs_be32 fl, uint8_t hlmit);
-void packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,
- ovs_16aligned_be32 addr[4],
- const struct in6_addr *new_addr,
- bool recalculate_csum);
-void packet_set_tcp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
-void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
-void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
-void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code);
-void packet_set_nd(struct dp_packet *, const struct in6_addr *target,
- const struct eth_addr sll, const struct eth_addr tll);
-void packet_set_nd_ext(struct dp_packet *packet,
- const ovs_16aligned_be32 rso_flags,
- const uint8_t opt_type);
-void packet_set_igmp3_query(struct dp_packet *, uint8_t max_resp,
- ovs_be32 group, bool srs, uint8_t qrv,
- uint8_t qqic);
-void *compose_ipv6(struct dp_packet *packet, uint8_t proto,
- const struct in6_addr *src, const struct in6_addr *dst,
- uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size);
-void compose_arp__(struct dp_packet *);
-void compose_arp(struct dp_packet *, uint16_t arp_op,
- const struct eth_addr arp_sha,
- const struct eth_addr arp_tha, bool broadcast,
- ovs_be32 arp_spa, ovs_be32 arp_tpa);
-void compose_nd_ns(struct dp_packet *, const struct eth_addr eth_src,
- const struct in6_addr *ipv6_src,
- const struct in6_addr *ipv6_dst);
-void compose_nd_na(struct dp_packet *, const struct eth_addr eth_src,
- const struct eth_addr eth_dst,
- const struct in6_addr *ipv6_src,
- const struct in6_addr *ipv6_dst,
- ovs_be32 rso_flags);
-void compose_nd_ra(struct dp_packet *,
- const struct eth_addr eth_src,
- const struct eth_addr eth_dst,
- const struct in6_addr *ipv6_src,
- const struct in6_addr *ipv6_dst,
- uint8_t cur_hop_limit, uint8_t mo_flags,
- ovs_be16 router_lt, ovs_be32 reachable_time,
- ovs_be32 retrans_timer, uint32_t mtu);
-void packet_put_ra_prefix_opt(struct dp_packet *,
- uint8_t plen, uint8_t la_flags,
- ovs_be32 valid_lifetime,
- ovs_be32 preferred_lifetime,
- const ovs_be128 router_prefix);
-bool packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr,
- bool *first_frag);
-void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6);
-void packet_tcp_complete_csum(struct dp_packet *, bool is_inner);
-void packet_udp_complete_csum(struct dp_packet *, bool is_inner);
-bool packet_udp_tunnel_csum(struct dp_packet *);
-void packet_sctp_complete_csum(struct dp_packet *, bool is_inner);
-
-
-#endif /* packets.h */
@@ -26,7 +26,6 @@
#include "dp-packet.h"
#include "flow.h"
#include "openvswitch/hmap.h"
-#include "packets.h"
#include "timeval.h"
#include "unaligned.h"
#include "util.h"
@@ -31,8 +31,8 @@
#include <string.h>
#include <unistd.h>
+#include "net-proto.h"
#include "ovs-router.h"
-#include "packets.h"
#include "openvswitch/vlog.h"
#include "util.h"
@@ -36,7 +36,6 @@
#include "openvswitch/list.h"
#include "openvswitch/ofpbuf.h"
#include "ovs-router.h"
-#include "packets.h"
#include "rtnetlink.h"
#include "tnl-ports.h"
#include "openvswitch/vlog.h"
@@ -36,7 +36,6 @@
#include "openvswitch/hmap.h"
#include "openvswitch/list.h"
#include "ovs-atomic.h"
-#include "packets.h"
enum admin_port_state {
RSTP_ADMIN_BRIDGE_PORT_STATE_DISABLED = 0,
@@ -40,7 +40,6 @@
#include "connectivity.h"
#include "openvswitch/ofpbuf.h"
#include "dp-packet.h"
-#include "packets.h"
#include "seq.h"
#include "unixctl.h"
#include "util.h"
@@ -42,7 +42,6 @@
#include "openvswitch/ofpbuf.h"
#include "ofproto/ofproto.h"
#include "dp-packet.h"
-#include "packets.h"
#include "seq.h"
#include "unixctl.h"
#include "util.h"
@@ -24,8 +24,8 @@
#include "netlink.h"
#include "netlink-notifier.h"
+#include "net-proto.h"
#include "openvswitch/ofpbuf.h"
-#include "packets.h"
#if IFLA_INFO_MAX < 5
#define IFLA_INFO_SLAVE_KIND 4
@@ -19,7 +19,7 @@
#include "hash.h"
#include "openvswitch/json.h"
-#include "packets.h"
+#include "net-proto.h"
#include "util.h"
#include "uuid.h"
@@ -36,8 +36,8 @@
#include <sys/un.h>
#include <unistd.h>
#include "openvswitch/dynamic-string.h"
+#include "net-proto.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "util.h"
#include "openvswitch/vlog.h"
@@ -30,7 +30,6 @@
#include "openvswitch/ofpbuf.h"
#include "ovs-atomic.h"
#include "dp-packet.h"
-#include "packets.h"
#include "seq.h"
#include "unixctl.h"
#include "util.h"
@@ -36,9 +36,9 @@
#include "coverage.h"
#include "openvswitch/dynamic-string.h"
#include "entropy.h"
+#include "net-proto.h"
#include "openvswitch/ofpbuf.h"
#include "openflow/openflow.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "openvswitch/shash.h"
#include "socket-util.h"
@@ -26,7 +26,6 @@
#include <sys/socket.h>
#include <unistd.h>
#include "openvswitch/dynamic-string.h"
-#include "packets.h"
#include "socket-util.h"
#include "util.h"
#include "stream-provider.h"
@@ -27,7 +27,6 @@
#include <string.h>
#include <unistd.h>
#include "ovs-atomic.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "socket-util.h"
#include "dirs.h"
@@ -35,7 +35,6 @@
#include "openvswitch/vlog.h"
#include "ovs-replay.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "random.h"
#include "socket-util.h"
@@ -43,7 +43,6 @@
#include "openvswitch/ofpbuf.h"
#include "openvswitch/util.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
#include "timeval.h"
#include "unaligned.h"
@@ -34,7 +34,6 @@
#include "netdev.h"
#include "ovs-atomic.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "seq.h"
#include "socket-util.h"
@@ -28,7 +28,6 @@
#include "flow.h"
#include "netdev.h"
-#include "packets.h"
#include "util.h"
int tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc,
@@ -21,7 +21,6 @@
#include <sys/socket.h>
#include "flow.h"
-#include "packets.h"
#include "util.h"
odp_port_t tnl_port_map_lookup(struct flow *flow, struct flow_wildcards *wc);
@@ -26,7 +26,6 @@
#include "odp-netlink.h"
#include "openvswitch/ofp-match.h"
#include "ovs-rcu.h"
-#include "packets.h"
#include "tun-metadata.h"
#include "util.h"
@@ -36,7 +36,6 @@
#include "openvswitch/ofp-util.h"
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "random.h"
#include "util.h"
@@ -40,7 +40,6 @@
#include "openvswitch/ofp-actions.h"
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "seq.h"
#include "openvswitch/shash.h"
@@ -20,7 +20,6 @@
#include <stdbool.h>
#include <stdint.h>
#include "ofproto-provider.h"
-#include "packets.h"
struct flow;
struct netdev;
@@ -37,7 +37,6 @@
#include "openvswitch/ofp-actions.h"
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "timeval.h"
@@ -30,7 +30,6 @@
#include "openvswitch/ofpbuf.h"
#include "ofproto.h"
#include "ofproto/netflow.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "socket-util.h"
#include "timeval.h"
@@ -29,7 +29,6 @@
#include "ofproto.h"
#include "ofproto-dpif.h"
#include "dp-packet.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "sset.h"
#include "util.h"
@@ -18,7 +18,6 @@
#include <stdint.h>
#include "openflow/openflow.h"
-#include "packets.h"
struct bfd;
struct cfm;
@@ -31,7 +31,6 @@
#include "netlink.h"
#include "openvswitch/ofpbuf.h"
#include "ofproto.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "ovs-router.h"
#include "route-table.h"
@@ -38,7 +38,6 @@
#include "ofproto-dpif-xlate-cache.h"
#include "ofproto-dpif-trace.h"
#include "ovs-rcu.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "seq.h"
#include "tunnel.h"
@@ -42,7 +42,6 @@
#include "openvswitch/dynamic-string.h"
#include "openvswitch/vlog.h"
#include "ovs-router.h"
-#include "packets.h"
#include "tnl-neigh-cache.h"
#include "util.h"
@@ -61,7 +61,6 @@
#include "openvswitch/vlog.h"
#include "ovs-lldp.h"
#include "ovs-router.h"
-#include "packets.h"
#include "tnl-neigh-cache.h"
#include "tnl-ports.h"
#include "tunnel.h"
@@ -53,7 +53,6 @@
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"
#include "ovs-rcu.h"
-#include "packets.h"
#include "pinsched.h"
#include "openvswitch/poll-loop.h"
#include "random.h"
@@ -26,7 +26,6 @@
#include "netdev.h"
#include "odp-util.h"
#include "openvswitch/ofpbuf.h"
-#include "packets.h"
#include "route-table.h"
#include "seq.h"
#include "smap.h"
@@ -35,13 +35,13 @@
#include "byte-order.h"
#include "classifier-private.h"
#include "command-line.h"
+#include "openvswitch/dynamic-string.h"
#include "fatal-signal.h"
#include "flow.h"
#include "openvswitch/vlog.h"
#include "ovstest.h"
#include "ovs-atomic.h"
#include "ovs-thread.h"
-#include "packets.h"
#include "random.h"
#include "timeval.h"
#include "unaligned.h"
@@ -18,6 +18,7 @@
#include "conntrack.h"
#include "dp-packet.h"
+#include "openvswitch/dynamic-string.h"
#include "fatal-signal.h"
#include "flow.h"
#include "netdev.h"
@@ -26,8 +26,8 @@
#include <stdlib.h>
#include <string.h>
#include "crc32c.h"
+#include "net-proto.h"
#include "ovstest.h"
-#include "packets.h"
#include "random.h"
#include "unaligned.h"
#include "util.h"
@@ -18,13 +18,14 @@
#undef NDEBUG
+#include <inttypes.h>
#include <linux/rtnetlink.h>
#include <stdio.h>
#include <stdlib.h>
#include "netlink-notifier.h"
+#include "net-proto.h"
#include "ovstest.h"
-#include "packets.h"
#include "route-table.h"
/* The following definition should be available in Linux 6.15 and might be
@@ -25,9 +25,9 @@
#include "command-line.h"
#include "daemon.h"
#include "openvswitch/dynamic-string.h"
+#include "net-proto.h"
#include "openvswitch/ofpbuf.h"
#include "ovstest.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "socket-util.h"
#include "unixctl.h"
@@ -19,7 +19,9 @@
#include <stdlib.h>
#include <linux/netfilter/nfnetlink.h>
+#include "net-proto.h"
#include "ct-dpif.h"
+#include "netlink.h"
#include "netlink-conntrack.h"
#include "netlink-notifier.h"
#include "ovstest.h"
@@ -16,11 +16,11 @@
#include <config.h>
#undef NDEBUG
-#include "packets.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "net-proto.h"
#include "ovstest.h"
static void
@@ -10,7 +10,6 @@
#include "openvswitch/ofpbuf.h"
#include "ovstest.h"
#include "dp-packet.h"
-#include "packets.h"
#include "openvswitch/vlog.h"
#define MAX_PORTS 10
@@ -30,9 +30,9 @@
#include "command-line.h"
#include "daemon.h"
#include "openvswitch/dynamic-string.h"
+#include "net-proto.h"
#include "openvswitch/ofpbuf.h"
#include "ovstest.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "socket-util.h"
#include "unixctl.h"
@@ -26,7 +26,6 @@
#include "dp-packet.h"
#include "openvswitch/ofpbuf.h"
#include "ovstest.h"
-#include "packets.h"
#include "openvswitch/vlog.h"
struct bpdu {
@@ -66,7 +66,6 @@
#include "openvswitch/shash.h"
#include "openvswitch/vconn.h"
#include "openvswitch/vlog.h"
-#include "packets.h"
#include "pcap-file.h"
#include "openvswitch/poll-loop.h"
#include "random.h"
@@ -74,6 +73,7 @@
#include "stream-ssl.h"
#include "socket-util.h"
#include "timeval.h"
+#include "tun-metadata.h"
#include "unixctl.h"
#include "util.h"
@@ -52,7 +52,6 @@
#include "openvswitch/vlog.h"
#include "ovs-lldp.h"
#include "ovs-numa.h"
-#include "packets.h"
#include "openvswitch/poll-loop.h"
#include "seq.h"
#include "sflow_api.h"
The leftover packets module was almost completely dealing with dp-packet work anyway, so fold it into the dp-packets translation unit to keep things consistent. During this process, also move some of the packet metadata stuff out and remove the packets translation unit. There were some additional cleanups here where packets.h was pulling in all sorts of other dependencies into translation units that didn't actually need them. So the .c files are widely updated to include just those headers they need (based on compiler warnings). Finally, there's a weird quirk in eth_push_vlan where a memmove optimization bug seems to pop up, so add a comment on why there are two warnings disabled. The dp_packet_resize_l2 calling order seems to matter, and an alternative is to force it to never inline that function, but it seems worse to just disabling the warnings. Signed-off-by: Aaron Conole <aconole@redhat.com> --- lib/automake.mk | 2 - lib/bfd.c | 1 - lib/bfd.h | 2 +- lib/cfm.c | 1 - lib/cfm.h | 1 - lib/classifier.c | 1 - lib/conntrack-private.h | 1 - lib/conntrack.h | 2 +- lib/ct-dpif.c | 1 + lib/ct-dpif.h | 3 +- lib/dhcp.h | 1 - lib/dp-packet.c | 1408 +++++++++++++++++++++++++++ lib/dp-packet.h | 106 ++- lib/dpctl.c | 1 - lib/dpif-netdev-extract-avx512.c | 1 - lib/dpif-netdev-lookup.c | 1 + lib/dpif-netdev-private-extract.c | 1 + lib/dpif-netdev-private-flow.h | 1 + lib/dpif-netdev.c | 1 - lib/dpif-netdev.h | 1 - lib/dpif-netlink-rtnl.c | 1 + lib/dpif-netlink.c | 1 - lib/dpif-offload-dpdk-netdev.c | 3 +- lib/dpif-offload-dpdk.c | 3 + lib/dpif.c | 1 - lib/dpif.h | 1 - lib/flow.c | 2 +- lib/flow.h | 157 ++- lib/ipf.c | 2 +- lib/lacp.c | 1 - lib/lacp.h | 6 +- lib/lldp/lldp.c | 1 - lib/lldp/lldpd-structs.h | 1 - lib/lldp/lldpd.c | 1 - lib/lldp/lldpd.h | 1 - lib/mac-learning.c | 2 + lib/mac-learning.h | 1 - lib/match.c | 1 - lib/mcast-snooping.h | 1 - lib/meta-flow.c | 1 - lib/multipath.c | 1 - lib/netdev-afxdp.c | 1 - lib/netdev-bsd.c | 1 - lib/netdev-dpdk.c | 1 - lib/netdev-dummy.c | 1 - lib/netdev-linux.c | 1 - lib/netdev-native-tnl.c | 4 +- lib/netdev-native-tnl.h | 1 - lib/netdev-provider.h | 1 - lib/netdev-vport.c | 1 - lib/netdev-windows.c | 1 - lib/netdev.c | 1 - lib/netdev.h | 1 - lib/nx-match.c | 2 +- lib/odp-execute-avx512.c | 2 +- lib/odp-execute-private.c | 1 + lib/odp-execute.c | 1 - lib/odp-util.c | 2 +- lib/odp-util.h | 1 + lib/ofp-ct.c | 2 + lib/ofp-ed-props.c | 2 - lib/ofp-match.c | 2 + lib/ofp-parse.c | 2 +- lib/ofp-print.c | 1 - lib/ofp-util.c | 1 - lib/ovs-lldp.c | 1 - lib/ovs-lldp.h | 1 - lib/ovs-router.c | 1 - lib/packets.c | 1420 ---------------------------- lib/packets.h | 282 ------ lib/pcap-file.c | 1 - lib/route-table-bsd.c | 2 +- lib/route-table.c | 1 - lib/rstp-common.h | 1 - lib/rstp-state-machines.c | 1 - lib/rstp.c | 1 - lib/rtnetlink.c | 2 +- lib/smap.c | 2 +- lib/socket-util.c | 2 +- lib/stp.c | 1 - lib/stream-ssl.c | 2 +- lib/stream-tcp.c | 1 - lib/stream-unix.c | 1 - lib/stream.c | 1 - lib/tc.c | 1 - lib/tnl-neigh-cache.c | 1 - lib/tnl-neigh-cache.h | 1 - lib/tnl-ports.h | 1 - lib/tun-metadata.c | 1 - lib/vconn.c | 1 - ofproto/bond.c | 1 - ofproto/bond.h | 1 - ofproto/in-band.c | 1 - ofproto/netflow.c | 1 - ofproto/ofproto-dpif-ipfix.c | 1 - ofproto/ofproto-dpif-monitor.h | 1 - ofproto/ofproto-dpif-sflow.c | 1 - ofproto/ofproto-dpif-upcall.c | 1 - ofproto/ofproto-dpif-xlate-cache.c | 1 - ofproto/ofproto-dpif-xlate.c | 1 - ofproto/ofproto.c | 1 - ofproto/tunnel.c | 1 - tests/test-classifier.c | 2 +- tests/test-conntrack.c | 1 + tests/test-csum.c | 2 +- tests/test-lib-route-table.c | 3 +- tests/test-netflow.c | 2 +- tests/test-netlink-conntrack.c | 2 + tests/test-packets.c | 2 +- tests/test-rstp.c | 1 - tests/test-sflow.c | 2 +- tests/test-stp.c | 1 - utilities/ovs-ofctl.c | 2 +- vswitchd/bridge.c | 1 - 114 files changed, 1719 insertions(+), 1804 deletions(-) delete mode 100644 lib/packets.c delete mode 100644 lib/packets.h