summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Scheurich <jan.scheurich@ericsson.com>2017-04-25 16:29:59 +0000
committerBen Pfaff <blp@ovn.org>2017-05-03 16:56:40 -0700
commit2482b0b0c8c4ceae1f7e4620cd8620ce144e1bf3 (patch)
treedca094fdddf67d6e24e686ecaf96485e48ffcb59
parentc2f4c39be4e288e7a08974aea53b18627a1ef9ef (diff)
downloadopenvswitch-2482b0b0c8c4ceae1f7e4620cd8620ce144e1bf3.tar.gz
userspace: Add packet_type in dp_packet and flow
This commit adds a packet_type attribute to the structs dp_packet and flow to explicitly carry the type of the packet as prepration for the introduction of the so-called packet type-aware pipeline (PTAP) in OVS. The packet_type is a big-endian 32 bit integer with the encoding as specified in OpenFlow verion 1.5. The upper 16 bits contain the packet type name space. Pre-defined values are defined in openflow-common.h: enum ofp_header_type_namespaces { OFPHTN_ONF = 0, /* ONF namespace. */ OFPHTN_ETHERTYPE = 1, /* ns_type is an Ethertype. */ OFPHTN_IP_PROTO = 2, /* ns_type is a IP protocol number. */ OFPHTN_UDP_TCP_PORT = 3, /* ns_type is a TCP or UDP port. */ OFPHTN_IPV4_OPTION = 4, /* ns_type is an IPv4 option number. */ }; The lower 16 bits specify the actual type in the context of the name space. Only name spaces 0 and 1 will be supported for now. For name space OFPHTN_ONF the relevant packet type is 0 (Ethernet). This is the default packet_type in OVS and the only one supported so far. Packets of type (OFPHTN_ONF, 0) are called Ethernet packets. In name space OFPHTN_ETHERTYPE the type is the Ethertype of the packet. A packet of type (OFPHTN_ETHERTYPE, <Ethertype>) is a standard L2 packet whith the Ethernet header (and any VLAN tags) removed to expose the L3 (or L2.5) payload of the packet. These will simply be called L3 packets. The Ethernet address fields dl_src and dl_dst in struct flow are not applicable for an L3 packet and must be zero. However, to maintain compatibility with the large code base, we have chosen to copy the Ethertype of an L3 packet into the the dl_type field of struct flow. This does not mean that it will be possible to match on dl_type for L3 packets with PTAP later on. Matching must be done on packet_type instead. New dp_packets are initialized with packet_type Ethernet. Ports that receive L3 packets will have to explicitly adjust the packet_type. Signed-off-by: Jean Tourrilhes <jt@labs.hpe.com> Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com> Co-authored-by: Zoltan Balogh <zoltan.balogh@ericsson.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--include/openflow/openflow-common.h9
-rw-r--r--include/openvswitch/flow.h16
-rw-r--r--include/openvswitch/ofp-print.h10
-rw-r--r--lib/cfm.c2
-rw-r--r--lib/conntrack.c2
-rw-r--r--lib/dp-packet.c3
-rw-r--r--lib/dp-packet.h18
-rw-r--r--lib/dpif-netdev.c3
-rw-r--r--lib/dpif-netlink.c18
-rw-r--r--lib/dpif.c7
-rw-r--r--lib/flow.c112
-rw-r--r--lib/flow.h11
-rw-r--r--lib/match.c2
-rw-r--r--lib/netdev-bsd.c1
-rw-r--r--lib/netdev-dummy.c5
-rw-r--r--lib/netdev-linux.c4
-rw-r--r--lib/netdev-native-tnl.c4
-rw-r--r--lib/nx-match.c2
-rw-r--r--lib/odp-execute.c2
-rw-r--r--lib/odp-util.h2
-rw-r--r--lib/ofp-print.c30
-rw-r--r--lib/ofp-util.c2
-rw-r--r--lib/packets.c10
-rw-r--r--lib/packets.h38
-rw-r--r--lib/pcap-file.c4
-rw-r--r--ofproto/ofproto-dpif-rid.h2
-rw-r--r--ofproto/ofproto-dpif-xlate.c2
-rw-r--r--ofproto/ofproto-dpif.c4
-rw-r--r--ovn/controller/pinctrl.c6
-rw-r--r--tests/test-flows.c2
30 files changed, 242 insertions, 91 deletions
diff --git a/include/openflow/openflow-common.h b/include/openflow/openflow-common.h
index 5936e3f09..3a0a57550 100644
--- a/include/openflow/openflow-common.h
+++ b/include/openflow/openflow-common.h
@@ -458,4 +458,13 @@ enum ofp_table_config {
OFPTC14_VACANCY_EVENTS = 1 << 3, /* Enable vacancy events. */
};
+/* Header and packet type name spaces. */
+enum ofp_header_type_namespaces {
+ OFPHTN_ONF = 0, /* ONF namespace. */
+ OFPHTN_ETHERTYPE = 1, /* ns_type is an Ethertype. */
+ OFPHTN_IP_PROTO = 2, /* ns_type is a IP protocol number. */
+ OFPHTN_UDP_TCP_PORT = 3, /* ns_type is a TCP or UDP port. */
+ OFPHTN_IPV4_OPTION = 4, /* ns_type is an IPv4 option number. */
+};
+
#endif /* openflow/openflow-common.h */
diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h
index 188467dc4..36a2a8577 100644
--- a/include/openvswitch/flow.h
+++ b/include/openvswitch/flow.h
@@ -23,7 +23,7 @@
/* This sequence number should be incremented whenever anything involving flows
* or the wildcarding of flows changes. This will cause build assertion
* failures in places which likely need to be updated. */
-#define FLOW_WC_SEQ 38
+#define FLOW_WC_SEQ 39
/* Number of Open vSwitch extension 32-bit registers. */
#define FLOW_N_REGS 16
@@ -108,7 +108,7 @@ struct flow {
uint8_t ct_nw_proto; /* CT orig tuple IP protocol. */
uint16_t ct_zone; /* Connection tracking zone. */
uint32_t ct_mark; /* Connection mark.*/
- uint8_t pad1[4]; /* Pad to 64 bits. */
+ ovs_be32 packet_type; /* OpenFlow packet type. */
ovs_u128 ct_label; /* Connection label. */
uint32_t conj_id; /* Conjunction ID. */
ofp_port_t actset_output; /* Output port in action set. */
@@ -116,8 +116,10 @@ struct flow {
/* L2, Order the same as in the Ethernet header! (64-bit aligned) */
struct eth_addr dl_dst; /* Ethernet destination address. */
struct eth_addr dl_src; /* Ethernet source address. */
- ovs_be16 dl_type; /* Ethernet frame type. */
- uint8_t pad2[2]; /* Pad to 64 bits. */
+ ovs_be16 dl_type; /* Ethernet frame type.
+ Note: This also holds the Ethertype for L3
+ packets of type PACKET_TYPE(1, Ethertype) */
+ uint8_t pad1[2]; /* Pad to 64 bits. */
union flow_vlan_hdr vlans[FLOW_MAX_VLAN_HEADERS]; /* VLANs */
ovs_be32 mpls_lse[ROUND_UP(FLOW_MAX_MPLS_LABELS, 2)]; /* MPLS label stack
(with padding). */
@@ -139,7 +141,7 @@ struct flow {
struct eth_addr arp_sha; /* ARP/ND source hardware address. */
struct eth_addr arp_tha; /* ARP/ND target hardware address. */
ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */
- ovs_be16 pad3; /* Pad to 64 bits. */
+ ovs_be16 pad2; /* Pad to 64 bits. */
/* L4 (64-bit aligned) */
ovs_be16 tp_src; /* TCP/UDP/SCTP source port/ICMP type. */
@@ -148,7 +150,7 @@ struct flow {
ovs_be16 ct_tp_dst; /* CT original tuple dst port/ICMP code. */
ovs_be32 igmp_group_ip4; /* IGMP group IPv4 address.
* Keep last for BUILD_ASSERT_DECL below. */
- ovs_be32 pad4; /* Pad to 64 bits. */
+ ovs_be32 pad3; /* Pad to 64 bits. */
};
BUILD_ASSERT_DECL(sizeof(struct flow) % sizeof(uint64_t) == 0);
BUILD_ASSERT_DECL(sizeof(struct flow_tnl) % sizeof(uint64_t) == 0);
@@ -158,7 +160,7 @@ BUILD_ASSERT_DECL(sizeof(struct flow_tnl) % sizeof(uint64_t) == 0);
/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t)
== sizeof(struct flow_tnl) + 300
- && FLOW_WC_SEQ == 38);
+ && FLOW_WC_SEQ == 39);
/* Incremental points at which flow classification may be performed in
* segments.
diff --git a/include/openvswitch/ofp-print.h b/include/openvswitch/ofp-print.h
index 863f7aaa2..08b642900 100644
--- a/include/openvswitch/ofp-print.h
+++ b/include/openvswitch/ofp-print.h
@@ -22,6 +22,8 @@
#include <stdint.h>
#include <stdio.h>
+#include <openvswitch/types.h>
+
struct ds;
struct ofp10_match;
struct ofp_flow_mod;
@@ -29,19 +31,23 @@ struct ofp_header;
struct ofputil_flow_stats;
struct ofputil_table_features;
struct ofputil_table_stats;
+struct dp_packet;
#ifdef __cplusplus
extern "C" {
#endif
void ofp_print(FILE *, const void *, size_t, int verbosity);
-void ofp_print_packet(FILE *stream, const void *data, size_t len);
+void ofp_print_packet(FILE *stream, const void *data,
+ size_t len, ovs_be32 packet_type);
+void ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet);
void ofp10_match_print(struct ds *, const struct ofp10_match *, int verbosity);
char *ofp_to_string(const void *, size_t, int verbosity);
char *ofp10_match_to_string(const struct ofp10_match *, int verbosity);
-char *ofp_packet_to_string(const void *data, size_t len);
+char *ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type);
+char *ofp_dp_packet_to_string(const struct dp_packet *packet);
void ofp_print_flow_stats(struct ds *, const struct ofputil_flow_stats *);
void ofp_print_version(const struct ofp_header *, struct ds *);
diff --git a/lib/cfm.c b/lib/cfm.c
index 7bc22e3bb..b6cfe4b11 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -760,7 +760,7 @@ cfm_process_heartbeat(struct cfm *cfm, const struct dp_packet *p)
atomic_read_relaxed(&cfm->extended, &extended);
- eth = dp_packet_l2(p);
+ eth = dp_packet_eth(p);
ccm = dp_packet_at(p, (uint8_t *)dp_packet_l3(p) - (uint8_t *)dp_packet_data(p),
CCM_ACCEPT_LEN);
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 60a397203..cb30ac751 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -970,7 +970,7 @@ static bool
conn_key_extract(struct conntrack *ct, struct dp_packet *pkt, ovs_be16 dl_type,
struct conn_lookup_ctx *ctx, uint16_t zone)
{
- const struct eth_header *l2 = dp_packet_l2(pkt);
+ const struct eth_header *l2 = dp_packet_eth(pkt);
const struct ip_header *l3 = dp_packet_l3(pkt);
const char *l4 = dp_packet_l4(pkt);
const char *tail = dp_packet_tail(pkt);
diff --git a/lib/dp-packet.c b/lib/dp-packet.c
index 793b54f14..67aa40618 100644
--- a/lib/dp-packet.c
+++ b/lib/dp-packet.c
@@ -32,6 +32,8 @@ dp_packet_init__(struct dp_packet *b, size_t allocated, enum dp_packet_source so
pkt_metadata_init(&b->md, 0);
dp_packet_rss_invalidate(b);
dp_packet_reset_cutlen(b);
+ /* By default assume the packet type to be Ethernet. */
+ b->packet_type = htonl(PT_ETH);
}
static void
@@ -171,6 +173,7 @@ dp_packet_clone_with_headroom(const struct dp_packet *buffer, size_t headroom)
new_buffer->l4_ofs = buffer->l4_ofs;
new_buffer->md = buffer->md;
new_buffer->cutlen = buffer->cutlen;
+ new_buffer->packet_type = buffer->packet_type;
#ifdef DPDK_NETDEV
new_buffer->mbuf.ol_flags = buffer->mbuf.ol_flags;
#else
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index c73ca19c5..d2549b186 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -29,6 +29,7 @@
#include "openvswitch/list.h"
#include "packets.h"
#include "util.h"
+#include "flow.h"
#ifdef __cplusplus
extern "C" {
@@ -46,6 +47,7 @@ enum OVS_PACKED_ENUM dp_packet_source {
/* Buffer for holding packet data. A dp_packet is automatically reallocated
* as necessary if it grows too large for the available memory.
+ * By default the packet type is set to Ethernet (PT_ETH).
*/
struct dp_packet {
#ifdef DPDK_NETDEV
@@ -67,6 +69,7 @@ struct dp_packet {
uint16_t l4_ofs; /* Transport-level header offset,
or UINT16_MAX. */
uint32_t cutlen; /* length in bytes to cut from the end. */
+ ovs_be32 packet_type; /* Packet type as defined in OpenFlow */
union {
struct pkt_metadata md;
uint64_t data[DP_PACKET_CONTEXT_SIZE / 8];
@@ -86,7 +89,7 @@ static inline void dp_packet_set_allocated(struct dp_packet *, uint16_t);
void *dp_packet_resize_l2(struct dp_packet *, int increment);
void *dp_packet_resize_l2_5(struct dp_packet *, int increment);
-static inline void *dp_packet_l2(const struct dp_packet *);
+static inline void *dp_packet_eth(const struct dp_packet *);
static inline void dp_packet_reset_offsets(struct dp_packet *);
static inline uint8_t dp_packet_l2_pad_size(const struct dp_packet *);
static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint8_t);
@@ -262,12 +265,19 @@ dp_packet_equal(const struct dp_packet *a, const struct dp_packet *b)
!memcmp(dp_packet_data(a), dp_packet_data(b), dp_packet_size(a));
}
-/* Get the start of the Ethernet frame. 'l3_ofs' marks the end of the l2
+static inline bool
+dp_packet_is_eth(const struct dp_packet *b)
+{
+ return b->packet_type == htonl(PT_ETH);
+}
+
+/* Get the start of the Ethernet frame. 'l3_ofs' marks the end of the l2
* headers, so return NULL if it is not set. */
static inline void *
-dp_packet_l2(const struct dp_packet *b)
+dp_packet_eth(const struct dp_packet *b)
{
- return (b->l3_ofs != UINT16_MAX) ? dp_packet_data(b) : NULL;
+ return (dp_packet_is_eth(b) && b->l3_ofs != UINT16_MAX)
+ ? dp_packet_data(b) : NULL;
}
/* Resets all layer offsets. 'l3' offset must be set before 'l2' can be
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index f4de737e3..4ee5d058a 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -4374,8 +4374,7 @@ dp_netdev_upcall(struct dp_netdev_pmd_thread *pmd, struct dp_packet *packet_,
ofpbuf_init(&key, 0);
odp_flow_key_from_flow(&odp_parms, &key);
- packet_str = ofp_packet_to_string(dp_packet_data(packet_),
- dp_packet_size(packet_));
+ packet_str = ofp_dp_packet_to_string(packet_);
odp_flow_key_format(key.data, key.size, &ds);
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index e27524754..319808f90 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -55,6 +55,7 @@
#include "unaligned.h"
#include "util.h"
#include "openvswitch/vlog.h"
+#include "openvswitch/flow.h"
VLOG_DEFINE_THIS_MODULE(dpif_netlink);
#ifdef _WIN32
@@ -2042,6 +2043,23 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
(char *)dp_packet_data(&upcall->packet) + sizeof(struct nlattr));
dp_packet_set_size(&upcall->packet, nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]));
+ if (nl_attr_find__(upcall->key, upcall->key_len, OVS_KEY_ATTR_ETHERNET)) {
+ /* Ethernet frame */
+ upcall->packet.packet_type = htonl(PT_ETH);
+ } else {
+ /* Non-Ethernet packet. Get the Ethertype from the NL attributes */
+ ovs_be16 ethertype = 0;
+ const struct nlattr *et_nla = nl_attr_find__(upcall->key,
+ upcall->key_len,
+ OVS_KEY_ATTR_ETHERTYPE);
+ if (et_nla) {
+ ethertype = nl_attr_get_be16(et_nla);
+ }
+ upcall->packet.packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,
+ ntohs(ethertype));
+ dp_packet_set_l3(&upcall->packet, dp_packet_data(&upcall->packet));
+ }
+
*dp_ifindex = ovs_header->dp_ifindex;
return 0;
diff --git a/lib/dpif.c b/lib/dpif.c
index 4066f9c55..44f63f8a3 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1466,8 +1466,7 @@ dpif_print_packet(struct dpif *dpif, struct dpif_upcall *upcall)
struct ds flow;
char *packet;
- packet = ofp_packet_to_string(dp_packet_data(&upcall->packet),
- dp_packet_size(&upcall->packet));
+ packet = ofp_dp_packet_to_string(&upcall->packet);
ds_init(&flow);
odp_flow_key_format(upcall->key, upcall->key_len, &flow);
@@ -1764,9 +1763,9 @@ log_execute_message(struct dpif *dpif, const struct dpif_execute *execute,
struct ofpbuf md = OFPBUF_STUB_INITIALIZER(stub);
packet = ofp_packet_to_string(dp_packet_data(execute->packet),
- dp_packet_size(execute->packet));
+ dp_packet_size(execute->packet),
+ execute->packet->packet_type);
odp_key_from_pkt_metadata(&md, &execute->packet->md);
-
ds_put_format(&ds, "%s: %sexecute ",
dpif_name(dpif),
(subexecute ? "sub-"
diff --git a/lib/flow.c b/lib/flow.c
index 07b13976e..69362229a 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -125,7 +125,7 @@ struct mf_ctx {
* away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are
* defined as macros. */
-#if (FLOW_WC_SEQ != 38)
+#if (FLOW_WC_SEQ != 39)
#define MINIFLOW_ASSERT(X) ovs_assert(X)
BUILD_MESSAGE("FLOW_WC_SEQ changed: miniflow_extract() will have runtime "
"assertions enabled. Consider updating FLOW_WC_SEQ after "
@@ -530,22 +530,31 @@ parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto,
return parse_ipv6_ext_hdrs__(datap, sizep, nw_proto, nw_frag);
}
-/* Initializes 'flow' members from 'packet' and 'md'
+/* Initializes 'flow' members from 'packet' and 'md', taking the packet type
+ * into account.
*
- * Initializes 'packet' header l2 pointer to the start of the Ethernet
- * header, and the layer offsets as follows:
+ * Initializes the layer offsets as follows:
*
- * - packet->l2_5_ofs to the start of the MPLS shim header, or UINT16_MAX
- * when there is no MPLS shim header.
+ * - packet->l2_5_ofs to the
+ * * the start of the MPLS shim header. Can be zero, if the
+ * packet is of type (OFPHTN_ETHERTYPE, ETH_TYPE_MPLS).
+ * * UINT16_MAX when there is no MPLS shim header.
*
- * - packet->l3_ofs to just past the Ethernet header, or just past the
- * vlan_header if one is present, to the first byte of the payload of the
- * Ethernet frame. UINT16_MAX if the frame is too short to contain an
- * Ethernet header.
+ * - packet->l3_ofs is set to
+ * * zero if the packet_type is in name space OFPHTN_ETHERTYPE
+ * and there is no MPLS shim header.
+ * * just past the Ethernet header, or just past the vlan_header if
+ * one is present, to the first byte of the payload of the
+ * Ethernet frame if the packet type is Ethernet and there is
+ * no MPLS shim header.
+ * * just past the MPLS label stack to the first byte of the MPLS
+ * payload if there is at least one MPLS shim header.
+ * * UINT16_MAX if the packet type is Ethernet and the frame is
+ * too short to contain an Ethernet header.
*
- * - packet->l4_ofs to just past the IPv4 header, if one is present and
- * has at least the content used for the fields of interest for the flow,
- * otherwise UINT16_MAX.
+ * - packet->l4_ofs is set to just past the IPv4 or IPv6 header, if one is
+ * present and the packet has at least the content used for the fields
+ * of interest for the flow, otherwise UINT16_MAX.
*/
void
flow_extract(struct dp_packet *packet, struct flow *flow)
@@ -569,11 +578,12 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
const struct pkt_metadata *md = &packet->md;
const void *data = dp_packet_data(packet);
size_t size = dp_packet_size(packet);
+ ovs_be32 packet_type = packet->packet_type;
uint64_t *values = miniflow_values(dst);
struct mf_ctx mf = { FLOWMAP_EMPTY_INITIALIZER, values,
values + FLOW_U64S };
- const char *l2;
- ovs_be16 dl_type;
+ const char *frame;
+ ovs_be16 dl_type = OVS_BE16_MAX;
uint8_t nw_frag, nw_tos, nw_ttl, nw_proto;
uint8_t *ct_nw_proto_p = NULL;
ovs_be16 ct_tp_src = 0, ct_tp_dst = 0;
@@ -617,37 +627,49 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
if (md->ct_state) {
miniflow_push_uint32(mf, ct_mark, md->ct_mark);
- miniflow_pad_to_64(mf, ct_mark);
+ miniflow_push_be32(mf, packet_type, packet_type);
if (!ovs_u128_is_zero(md->ct_label)) {
miniflow_push_words(mf, ct_label, &md->ct_label,
sizeof md->ct_label / sizeof(uint64_t));
}
+ } else {
+ miniflow_pad_from_64(mf, packet_type);
+ miniflow_push_be32(mf, packet_type, packet_type);
}
/* Initialize packet's layer pointer and offsets. */
- l2 = data;
+ frame = data;
dp_packet_reset_offsets(packet);
- /* Must have full Ethernet header to proceed. */
- if (OVS_UNLIKELY(size < sizeof(struct eth_header))) {
- goto out;
- } else {
- /* Link layer. */
- ASSERT_SEQUENTIAL(dl_dst, dl_src);
- miniflow_push_macs(mf, dl_dst, data);
-
- /* VLAN */
- union flow_vlan_hdr vlans[FLOW_MAX_VLAN_HEADERS];
- size_t num_vlans = parse_vlan(&data, &size, vlans);
+ if (packet_type == htonl(PT_ETH)) {
+ /* Must have full Ethernet header to proceed. */
+ if (OVS_UNLIKELY(size < sizeof(struct eth_header))) {
+ goto out;
+ } else {
+ /* Link layer. */
+ ASSERT_SEQUENTIAL(dl_dst, dl_src);
+ miniflow_push_macs(mf, dl_dst, data);
+
+ /* VLAN */
+ union flow_vlan_hdr vlans[FLOW_MAX_VLAN_HEADERS];
+ size_t num_vlans = parse_vlan(&data, &size, vlans);
+
+ dl_type = parse_ethertype(&data, &size);
+ miniflow_push_be16(mf, dl_type, dl_type);
+ miniflow_pad_to_64(mf, dl_type);
+ if (num_vlans > 0) {
+ miniflow_push_words_32(mf, vlans, vlans, num_vlans);
+ }
- /* dl_type */
- dl_type = parse_ethertype(&data, &size);
+ }
+ } else {
+ /* Take dl_type from packet_type. */
+ dl_type = pt_ns_type_be(packet_type);
+ miniflow_pad_from_64(mf, dl_type);
miniflow_push_be16(mf, dl_type, dl_type);
+ /* Do not push vlan_tci, pad instead */
miniflow_pad_to_64(mf, dl_type);
- if (num_vlans > 0) {
- miniflow_push_words_32(mf, vlans, vlans, num_vlans);
- }
}
/* Parse mpls. */
@@ -655,13 +677,13 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
int count;
const void *mpls = data;
- packet->l2_5_ofs = (char *)data - l2;
+ packet->l2_5_ofs = (char *)data - frame;
count = parse_mpls(&data, &size);
miniflow_push_words_32(mf, mpls_lse, mpls, count);
}
/* Network layer. */
- packet->l3_ofs = (char *)data - l2;
+ packet->l3_ofs = (char *)data - frame;
nw_frag = 0;
if (OVS_LIKELY(dl_type == htons(ETH_TYPE_IP))) {
@@ -798,7 +820,7 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
goto out;
}
- packet->l4_ofs = (char *)data - l2;
+ packet->l4_ofs = (char *)data - frame;
miniflow_push_be32(mf, nw_frag,
BYTES_TO_BE32(nw_frag, nw_tos, nw_ttl, nw_proto));
@@ -927,7 +949,7 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
match_init_catchall(flow_metadata);
if (flow->tunnel.tun_id != htonll(0)) {
@@ -1382,7 +1404,7 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
memset(&wc->masks, 0x0, sizeof wc->masks);
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
if (flow_tnl_dst_is_set(&flow->tunnel)) {
if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
@@ -1399,6 +1421,7 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
WC_MASK_FIELD(wc, tunnel.tp_dst);
WC_MASK_FIELD(wc, tunnel.gbp_id);
WC_MASK_FIELD(wc, tunnel.gbp_flags);
+ WC_MASK_FIELD(wc, packet_type);
if (!(flow->tunnel.flags & FLOW_TNL_F_UDPIF)) {
if (flow->tunnel.metadata.present.map) {
@@ -1517,7 +1540,7 @@ void
flow_wc_map(const struct flow *flow, struct flowmap *map)
{
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
flowmap_init(map);
@@ -1548,6 +1571,7 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
FLOWMAP_SET(map, ct_zone);
FLOWMAP_SET(map, ct_mark);
FLOWMAP_SET(map, ct_label);
+ FLOWMAP_SET(map, packet_type);
/* Ethertype-dependent fields. */
if (OVS_LIKELY(flow->dl_type == htons(ETH_TYPE_IP))) {
@@ -1611,7 +1635,7 @@ void
flow_wildcards_clear_non_packet_fields(struct flow_wildcards *wc)
{
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata);
memset(&wc->masks.regs, 0, sizeof wc->masks.regs);
@@ -1755,7 +1779,7 @@ flow_wildcards_set_xxreg_mask(struct flow_wildcards *wc, int idx,
uint32_t
miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
uint32_t hash = basis;
if (flow) {
@@ -1802,7 +1826,7 @@ ASSERT_SEQUENTIAL(ipv6_src, ipv6_dst);
uint32_t
flow_hash_5tuple(const struct flow *flow, uint32_t basis)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
uint32_t hash = basis;
if (flow) {
@@ -2391,7 +2415,7 @@ flow_push_mpls(struct flow *flow, int n, ovs_be16 mpls_eth_type,
if (clear_flow_L3) {
/* Clear all L3 and L4 fields and dp_hash. */
- BUILD_ASSERT(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT(FLOW_WC_SEQ == 39);
memset((char *) flow + FLOW_SEGMENT_2_ENDS_AT, 0,
sizeof(struct flow) - FLOW_SEGMENT_2_ENDS_AT);
flow->dp_hash = 0;
@@ -2616,7 +2640,7 @@ flow_compose(struct dp_packet *p, const struct flow *flow)
/* eth_compose() sets l3 pointer and makes sure it is 32-bit aligned. */
eth_compose(p, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0);
if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) {
- struct eth_header *eth = dp_packet_l2(p);
+ struct eth_header *eth = dp_packet_eth(p);
eth->eth_type = htons(dp_packet_size(p));
return;
}
diff --git a/lib/flow.h b/lib/flow.h
index 2957108a6..94c8a0c4e 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -908,7 +908,7 @@ static inline void
pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow)
{
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
md->recirc_id = flow->recirc_id;
md->dp_hash = flow->dp_hash;
@@ -953,6 +953,15 @@ pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow)
#define FLOW_WC_GET_AND_MASK_WC(FLOW, WC, FIELD) \
(((WC) ? WC_MASK_FIELD(WC, FIELD) : NULL), ((FLOW)->FIELD))
+static inline bool is_ethernet(const struct flow *flow,
+ struct flow_wildcards *wc)
+{
+ if (wc) {
+ WC_MASK_FIELD(wc, packet_type);
+ }
+ return flow->packet_type == htonl(PT_ETH);
+}
+
static inline bool is_vlan(const struct flow *flow,
struct flow_wildcards *wc)
{
diff --git a/lib/match.c b/lib/match.c
index e50b134a8..96b1850b8 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -1169,7 +1169,7 @@ match_format(const struct match *match, struct ds *s, int priority)
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
if (priority != OFP_DEFAULT_PRIORITY) {
ds_put_format(s, "%spriority=%s%d,",
diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
index 94c515d5a..c51646a4f 100644
--- a/lib/netdev-bsd.c
+++ b/lib/netdev-bsd.c
@@ -630,6 +630,7 @@ netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch)
mtu = ETH_PAYLOAD_MAX;
}
+ /* Assume Ethernet port. No need to set packet_type. */
packet = dp_packet_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu,
DP_NETDEV_HEADROOM);
retval = (rxq->pcap_handle
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 065743420..d973d7e7d 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1067,6 +1067,11 @@ netdev_dummy_send(struct netdev *netdev, int qid OVS_UNUSED,
const void *buffer = dp_packet_data(packet);
size_t size = dp_packet_size(packet);
+ if (batch->packets[i]->packet_type != htonl(PT_ETH)) {
+ error = EPFNOSUPPORT;
+ break;
+ }
+
size -= dp_packet_get_cutlen(packet);
if (size < ETH_HEADER_LEN) {
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 79e827303..3ad3d454c 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -1133,6 +1133,7 @@ netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch)
mtu = ETH_PAYLOAD_MAX;
}
+ /* Assume Ethernet port. No need to set packet_type. */
buffer = dp_packet_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu,
DP_NETDEV_HEADROOM);
retval = (rx->is_tap
@@ -5525,7 +5526,8 @@ get_etheraddr(const char *netdev_name, struct eth_addr *ea)
return error;
}
hwaddr_family = ifr.ifr_hwaddr.sa_family;
- if (hwaddr_family != AF_UNSPEC && hwaddr_family != ARPHRD_ETHER) {
+ if (hwaddr_family != AF_UNSPEC && hwaddr_family != ARPHRD_ETHER &&
+ hwaddr_family != ARPHRD_NONE) {
VLOG_INFO("%s device has unknown hardware address family %d",
netdev_name, hwaddr_family);
return EINVAL;
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index c730e7234..2798324f5 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -191,7 +191,7 @@ udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
csum = csum_continue(csum, udp, dp_packet_size(packet) -
((const unsigned char *)udp -
- (const unsigned char *)dp_packet_l2(packet)
+ (const unsigned char *)dp_packet_eth(packet)
));
if (csum_finish(csum)) {
return NULL;
@@ -370,7 +370,7 @@ parse_gre_header(struct dp_packet *packet,
pkt_csum = csum(greh, dp_packet_size(packet) -
((const unsigned char *)greh -
- (const unsigned char *)dp_packet_l2(packet)));
+ (const unsigned char *)dp_packet_eth(packet)));
if (pkt_csum) {
return -EINVAL;
}
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 8fcae977c..68e58d393 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -986,7 +986,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
int match_len;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
/* Metadata. */
if (match->wc.masks.dp_hash) {
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index b03cbd4ad..c4563b1f8 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -51,7 +51,7 @@ static void
odp_eth_set_addrs(struct dp_packet *packet, const struct ovs_key_ethernet *key,
const struct ovs_key_ethernet *mask)
{
- struct eth_header *eh = dp_packet_l2(packet);
+ struct eth_header *eh = dp_packet_eth(packet);
if (eh) {
if (!mask) {
diff --git a/lib/odp-util.h b/lib/odp-util.h
index ab9be55f0..45686d025 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -143,7 +143,7 @@ void odp_portno_names_destroy(struct hmap *portno_names);
* add another field and forget to adjust this value.
*/
#define ODPUTIL_FLOW_KEY_BYTES 640
-BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
/* A buffer with sufficient size and alignment to hold an nlattr-formatted flow
* key. An array of "struct nlattr" might not, in theory, be sufficiently
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index ab07434d0..7ca953100 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -58,7 +58,7 @@ static void ofp_print_error(struct ds *, enum ofperr);
/* Returns a string that represents the contents of the Ethernet frame in the
* 'len' bytes starting at 'data'. The caller must free the returned string.*/
char *
-ofp_packet_to_string(const void *data, size_t len)
+ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type)
{
struct ds ds = DS_EMPTY_INITIALIZER;
struct dp_packet buf;
@@ -66,6 +66,7 @@ ofp_packet_to_string(const void *data, size_t len)
size_t l4_size;
dp_packet_use_const(&buf, data, len);
+ buf.packet_type = packet_type;
flow_extract(&buf, &flow);
flow_format(&ds, &flow);
@@ -96,6 +97,14 @@ ofp_packet_to_string(const void *data, size_t len)
return ds_cstr(&ds);
}
+char *
+ofp_dp_packet_to_string(const struct dp_packet *packet)
+{
+ return ofp_packet_to_string(dp_packet_data(packet),
+ dp_packet_size(packet),
+ packet->packet_type);
+}
+
static void
format_hex_arg(struct ds *s, const uint8_t *data, size_t len)
{
@@ -208,8 +217,10 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
}
if (verbosity > 0) {
+ /* Packet In can only carry Ethernet packets. */
char *packet = ofp_packet_to_string(public->packet,
- public->packet_len);
+ public->packet_len,
+ htonl(PT_ETH));
ds_put_cstr(string, packet);
free(packet);
}
@@ -245,7 +256,9 @@ ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
if (po.buffer_id == UINT32_MAX) {
ds_put_format(string, " data_len=%"PRIuSIZE, po.packet_len);
if (verbosity > 0 && po.packet_len > 0) {
- char *packet = ofp_packet_to_string(po.packet, po.packet_len);
+ /* Packet Out can only carry Ethernet packets. */
+ char *packet = ofp_packet_to_string(po.packet, po.packet_len,
+ htonl(PT_ETH));
ds_put_char(string, '\n');
ds_put_cstr(string, packet);
free(packet);
@@ -3760,7 +3773,14 @@ ofp_print(FILE *stream, const void *oh, size_t len, int verbosity)
/* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
* 'data' to 'stream'. */
void
-ofp_print_packet(FILE *stream, const void *data, size_t len)
+ofp_print_packet(FILE *stream, const void *data, size_t len,
+ ovs_be32 packet_type)
+{
+ print_and_free(stream, ofp_packet_to_string(data, len, packet_type));
+}
+
+void
+ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
{
- print_and_free(stream, ofp_packet_to_string(data, len));
+ print_and_free(stream, ofp_dp_packet_to_string(packet));
}
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 1f038c61e..bdf89b6c3 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -101,7 +101,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
/* Initialize most of wc. */
flow_wildcards_init_catchall(wc);
diff --git a/lib/packets.c b/lib/packets.c
index 94e7d8721..26781b0e3 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -190,6 +190,7 @@ compose_rarp(struct dp_packet *b, const struct eth_addr eth_src)
dp_packet_reset_offsets(b);
dp_packet_set_l3(b, arp);
+ b->packet_type = htonl(PT_ETH);
}
/* Insert VLAN header according to given TCI. Packet passed must be Ethernet
@@ -215,7 +216,7 @@ eth_push_vlan(struct dp_packet *packet, ovs_be16 tpid, ovs_be16 tci)
void
eth_pop_vlan(struct dp_packet *packet)
{
- struct vlan_eth_header *veh = dp_packet_l2(packet);
+ struct vlan_eth_header *veh = dp_packet_eth(packet);
if (veh && dp_packet_size(packet) >= sizeof *veh
&& eth_type_vlan(veh->veth_type)) {
@@ -229,7 +230,7 @@ eth_pop_vlan(struct dp_packet *packet)
static void
set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)
{
- struct eth_header *eh = dp_packet_l2(packet);
+ struct eth_header *eh = dp_packet_eth(packet);
if (!eh) {
return;
@@ -843,6 +844,7 @@ eth_compose(struct dp_packet *b, const struct eth_addr eth_dst,
eth->eth_src = eth_src;
eth->eth_type = htons(eth_type);
+ b->packet_type = htonl(PT_ETH);
dp_packet_reset_offsets(b);
dp_packet_set_l3(b, data);
@@ -1307,7 +1309,7 @@ compose_arp(struct dp_packet *b, uint16_t arp_op,
{
compose_arp__(b);
- struct eth_header *eth = dp_packet_l2(b);
+ struct eth_header *eth = dp_packet_eth(b);
eth->eth_dst = broadcast ? eth_addr_broadcast : arp_tha;
eth->eth_src = arp_sha;
@@ -1341,6 +1343,8 @@ compose_arp__(struct dp_packet *b)
dp_packet_reset_offsets(b);
dp_packet_set_l3(b, arp);
+
+ b->packet_type = htonl(PT_ETH);
}
/* This function expects packet with ethernet header with correct
diff --git a/lib/packets.h b/lib/packets.h
index 639f5e44d..8acfbf508 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -1130,6 +1130,44 @@ struct vxlanhdr {
#define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
+/* Input values for PACKET_TYPE macros have to be in host byte order.
+ * The _BE postfix indicates result is in network byte order. Otherwise result
+ * is in host byte order. */
+#define PACKET_TYPE(NS, NS_TYPE) ((uint32_t) ((NS) << 16 | (NS_TYPE)))
+#define PACKET_TYPE_BE(NS, NS_TYPE) (htonl((NS) << 16 | (NS_TYPE)))
+
+/* Returns the host byte ordered namespace of 'packet type'. */
+static inline uint16_t
+pt_ns(ovs_be32 packet_type)
+{
+ return ntohl(packet_type) >> 16;
+}
+
+/* Returns the network byte ordered namespace type of 'packet type'. */
+static inline ovs_be16
+pt_ns_type_be(ovs_be32 packet_type)
+{
+ return be32_to_be16(packet_type);
+}
+
+/* Returns the host byte ordered namespace type of 'packet type'. */
+static inline uint16_t
+pt_ns_type(ovs_be32 packet_type)
+{
+ return ntohs(pt_ns_type_be(packet_type));
+}
+
+/* Well-known packet_type field values. */
+enum packet_type {
+ PT_ETH = PACKET_TYPE(OFPHTN_ONF, 0x0000), /* Default: Ethernet */
+ PT_IPV4 = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_IP),
+ PT_IPV6 = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_IPV6),
+ PT_MPLS = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS),
+ PT_MPLS_MC = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS_MCAST),
+ PT_UNKNOWN = PACKET_TYPE(0xffff, 0xffff), /* Unknown packet type. */
+};
+
+
void ipv6_format_addr(const struct in6_addr *addr, struct ds *);
void ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *,
bool bracket);
diff --git a/lib/pcap-file.c b/lib/pcap-file.c
index dd4d22930..981d56d48 100644
--- a/lib/pcap-file.c
+++ b/lib/pcap-file.c
@@ -177,7 +177,7 @@ ovs_pcap_read(FILE *file, struct dp_packet **bufp, long long int *when)
*when = ts_sec * 1000LL + ts_usec / 1000;
}
- /* Read packet. */
+ /* Read packet. Packet type is Ethernet */
buf = dp_packet_new(len);
data = dp_packet_put_uninit(buf, len);
if (fread(data, len, 1, file) != 1) {
@@ -197,6 +197,8 @@ ovs_pcap_write(FILE *file, struct dp_packet *buf)
struct pcaprec_hdr prh;
struct timeval tv;
+ ovs_assert(buf->packet_type == htonl(PT_ETH));
+
xgettimeofday(&tv);
prh.ts_sec = tv.tv_sec;
prh.ts_usec = tv.tv_usec;
diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h
index 2c05c3607..ab9b1b7e5 100644
--- a/ofproto/ofproto-dpif-rid.h
+++ b/ofproto/ofproto-dpif-rid.h
@@ -99,7 +99,7 @@ struct rule;
/* Metadata for restoring pipeline context after recirculation. Helpers
* are inlined below to keep them together with the definition for easier
* updates. */
-BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
struct frozen_metadata {
/* Metadata in struct flow. */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 16dae15bb..b308f21de 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -3407,7 +3407,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
/* If 'struct flow' gets additional metadata, we'll need to zero it out
* before traversing a patch port. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39);
memset(&flow_tnl, 0, sizeof flow_tnl);
if (!xport) {
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 9c3a5673c..dc5f004cd 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2286,7 +2286,7 @@ rstp_send_bpdu_cb(struct dp_packet *pkt, void *ofport_, void *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_;
struct ofport_dpif *ofport = ofport_;
- struct eth_header *eth = dp_packet_l2(pkt);
+ struct eth_header *eth = dp_packet_eth(pkt);
netdev_get_etheraddr(ofport->up.netdev, &eth->eth_src);
if (eth_addr_is_zero(eth->eth_src)) {
@@ -2311,7 +2311,7 @@ send_bpdu_cb(struct dp_packet *pkt, int port_num, void *ofproto_)
VLOG_WARN_RL(&rl, "%s: cannot send BPDU on unknown port %d",
ofproto->up.name, port_num);
} else {
- struct eth_header *eth = dp_packet_l2(pkt);
+ struct eth_header *eth = dp_packet_eth(pkt);
netdev_get_etheraddr(ofport->up.netdev, &eth->eth_src);
if (eth_addr_is_zero(eth->eth_src)) {
diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
index 4b443595b..9ad413376 100644
--- a/ovn/controller/pinctrl.c
+++ b/ovn/controller/pinctrl.c
@@ -143,7 +143,7 @@ pinctrl_handle_arp(const struct flow *ip_flow, const struct match *md,
dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
compose_arp__(&packet);
- struct eth_header *eth = dp_packet_l2(&packet);
+ struct eth_header *eth = dp_packet_eth(&packet);
eth->eth_dst = ip_flow->dl_dst;
eth->eth_src = ip_flow->dl_src;
@@ -361,7 +361,7 @@ pinctrl_handle_put_dhcp_opts(
/* Log the response. */
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(20, 40);
- const struct eth_header *l2 = dp_packet_l2(&pkt_out);
+ const struct eth_header *l2 = dp_packet_eth(&pkt_out);
VLOG_INFO_RL(&rl, "DHCP%s "ETH_ADDR_FMT" "IP_FMT"",
msg_type == DHCP_MSG_OFFER ? "OFFER" : "ACK",
ETH_ADDR_ARGS(l2->eth_src), IP_ARGS(*offer_ip));
@@ -641,7 +641,7 @@ pinctrl_handle_put_dhcpv6_opts(
csum = packet_csum_pseudoheader6(dp_packet_l3(&pkt_out));
csum = csum_continue(csum, out_udp, dp_packet_size(&pkt_out) -
((const unsigned char *)out_udp -
- (const unsigned char *)dp_packet_l2(&pkt_out)));
+ (const unsigned char *)dp_packet_eth(&pkt_out)));
out_udp->udp_csum = csum_finish(csum);
if (!out_udp->udp_csum) {
out_udp->udp_csum = htons(0xffff);
diff --git a/tests/test-flows.c b/tests/test-flows.c
index 4a1b65ed2..067f36a49 100644
--- a/tests/test-flows.c
+++ b/tests/test-flows.c
@@ -83,7 +83,7 @@ test_flows_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
errors++;
printf("mismatch on packet #%d (1-based).\n", n);
printf("Packet:\n");
- ofp_print_packet(stdout, dp_packet_data(packet), dp_packet_size(packet));
+ ofp_print_packet(stdout, dp_packet_data(packet), dp_packet_size(packet), htonl(PT_ETH));
ovs_hex_dump(stdout, dp_packet_data(packet), dp_packet_size(packet), 0, true);
match_print(&match);
printf("Expected flow:\n%s\n", exp_s);