Skip to content

Commit

Permalink
userspace: Add packet_type in dp_packet and flow
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Jan Scheurich <[email protected]>
Co-authored-by: Zoltan Balogh <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
2 people authored and blp committed May 3, 2017
1 parent c2f4c39 commit 2482b0b
Show file tree
Hide file tree
Showing 30 changed files with 242 additions and 91 deletions.
9 changes: 9 additions & 0 deletions include/openflow/openflow-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
16 changes: 9 additions & 7 deletions include/openvswitch/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -108,16 +108,18 @@ 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. */

/* 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). */
Expand All @@ -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. */
Expand All @@ -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);
Expand All @@ -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.
Expand Down
10 changes: 8 additions & 2 deletions include/openvswitch/ofp-print.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,32 @@
#include <stdint.h>
#include <stdio.h>

#include <openvswitch/types.h>

struct ds;
struct ofp10_match;
struct ofp_flow_mod;
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 *);
Expand Down
2 changes: 1 addition & 1 deletion lib/cfm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion lib/conntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions lib/dp-packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
18 changes: 14 additions & 4 deletions lib/dp-packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "openvswitch/list.h"
#include "packets.h"
#include "util.h"
#include "flow.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -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
Expand All @@ -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];
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions lib/dpif-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
18 changes: 18 additions & 0 deletions lib/dpif-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 3 additions & 4 deletions lib/dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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-"
Expand Down
Loading

0 comments on commit 2482b0b

Please sign in to comment.