[ovs-dev] [RFC] dp-packet: Don't resize DPBUF_DPDK packets.
Tiago Lam
tiago.lam at intel.com
Fri Jul 20 18:01:43 UTC 2018
Up until now DPDK packets (DPBUF_DPDK) could call dp_packet_resize__()
without any constraint, leading to call OVS_NOT_REACHED() and premature
termination of the OvS process if one single packet didn't have enough
tailroom or headroom space for a specific operation, such as pushing or
popping a header.
To fix this, two functions are introduced, dp_packet_is_tailroom_avail()
and dp_packet_is_headroom_avail(), which are now used to check if
there's enough tailroom or headroom space, respectively, before
proceeding with calling the dp_packet_prealloc_tailroom() and
dp_packet_prealloc_headroom() functions, thus avoiding the call to
dp_packet_resize__() and OVS_NOT_REACHED() for DPDK packets.
Since put_uninit() and push_uninit() may now return NULL for DPDK
packets, the places where these operations may be called from a DPDK
packet now check for NULL and log a message where appropriate. For
example, eth_push_vlan() in packets.c, now returns 1 if the
push_uninit() operation on the packet fails. Later on, the caller,
odp_execute_actions(), drops the packet upon checking that the return is
different from 0 (error).
CC: Anju Thomas <anju.thomas at ericsson.com>
Reported-at:
https://mail.openvswitch.org/pipermail/ovs-dev/2018-May/346649.html
Signed-off-by: Tiago Lam <tiago.lam at intel.com>
---
lib/dp-packet.c | 126 +++++++++++++++++++++++++++++++++++++++++-------
lib/netdev-native-tnl.c | 24 +++++++--
lib/netdev-native-tnl.h | 6 +--
lib/netdev-provider.h | 2 +-
lib/netdev.c | 16 ++++--
lib/odp-execute.c | 49 +++++++++++++++----
lib/packets.c | 38 +++++++++++++--
lib/packets.h | 8 +--
8 files changed, 224 insertions(+), 45 deletions(-)
diff --git a/lib/dp-packet.c b/lib/dp-packet.c
index 443c225..058b653 100644
--- a/lib/dp-packet.c
+++ b/lib/dp-packet.c
@@ -239,6 +239,9 @@ dp_packet_resize__(struct dp_packet *b, size_t new_headroom, size_t new_tailroom
switch (b->source) {
case DPBUF_DPDK:
+ /* DPDK mbufs have a fixed layout, meaning they can't be resized per
+ * say. As a result, this operation shouldn't be called for DPBUF_DPDK
+ * packets */
OVS_NOT_REACHED();
case DPBUF_MALLOC:
@@ -273,9 +276,27 @@ dp_packet_resize__(struct dp_packet *b, size_t new_headroom, size_t new_tailroom
}
}
-/* Ensures that 'b' has room for at least 'size' bytes at its tail end,
- * reallocating and copying its data if necessary. Its headroom, if any, is
- * preserved. */
+static bool
+dp_packet_is_tailroom_avail(struct dp_packet *b, size_t size)
+{
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ if (size > dp_packet_tailroom(b)) {
+ return false;
+ }
+
+ return true;
+ }
+#endif
+ return true;
+}
+
+/* For non-DPDK packets, ensures that 'b' has room for at least 'size' bytes at
+ * its tail end, reallocating and copying its data if necessary. Its headroom,
+ * if any, is preserved.
+ *
+ * For DPDK packets, no reallocation is performed. The caller is responsible
+ * for ensuring there's enough tailroom space available. */
void
dp_packet_prealloc_tailroom(struct dp_packet *b, size_t size)
{
@@ -284,9 +305,27 @@ dp_packet_prealloc_tailroom(struct dp_packet *b, size_t size)
}
}
-/* Ensures that 'b' has room for at least 'size' bytes at its head,
- * reallocating and copying its data if necessary. Its tailroom, if any, is
- * preserved. */
+static bool
+dp_packet_is_headroom_avail(struct dp_packet *b, size_t size)
+{
+#ifdef DPDK_NETDEV
+ if (b->source == DPBUF_DPDK) {
+ if (size > dp_packet_headroom(b)) {
+ return false;
+ }
+
+ return true;
+ }
+#endif
+ return true;
+}
+
+/* For non-DPDK packets, ensures that 'b' has room for at least 'size' bytes at
+ * its head, reallocating and copying its data if necessary. Its tailroom, if
+ * any, is preserved.
+ *
+ * For DPDK packets, no reallocation is performed. The caller is responsible
+ * for ensuring there's enough headroom space available. */
void
dp_packet_prealloc_headroom(struct dp_packet *b, size_t size)
{
@@ -315,11 +354,19 @@ dp_packet_shift(struct dp_packet *b, int delta)
/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
* copying its data if necessary. Returns a pointer to the first byte of the
- * new data, which is left uninitialized. */
+ * new data, which is left uninitialized.
+ *
+ * For DPDK packets, no reallocation is performed and NULL may be returned if
+ * 'size' is bigger than the available tailroom space. */
void *
dp_packet_put_uninit(struct dp_packet *b, size_t size)
{
void *p;
+
+ if (!dp_packet_is_tailroom_avail(b, size)) {
+ return NULL;
+ }
+
dp_packet_prealloc_tailroom(b, size);
p = dp_packet_tail(b);
dp_packet_set_size(b, dp_packet_size(b) + size);
@@ -328,22 +375,34 @@ dp_packet_put_uninit(struct dp_packet *b, size_t size)
/* Appends 'size' zeroed bytes to the tail end of 'b'. Data in 'b' is
* reallocated and copied if necessary. Returns a pointer to the first byte of
- * the data's location in the dp_packet. */
+ * the data's location in the dp_packet.
+ *
+ * For DPDK packets, no reallocation is performed and NULL may be returned if
+ * 'size' is bigger than the available tailroom space. */
void *
dp_packet_put_zeros(struct dp_packet *b, size_t size)
{
void *dst = dp_packet_put_uninit(b, size);
+ if (!dst) {
+ return NULL;
+ }
memset(dst, 0, size);
return dst;
}
/* Appends the 'size' bytes of data in 'p' to the tail end of 'b'. Data in 'b'
* is reallocated and copied if necessary. Returns a pointer to the first
- * byte of the data's location in the dp_packet. */
+ * byte of the data's location in the dp_packet.
+ *
+ * For DPDK packets, no reallocation is performed and NULL may be returned if
+ * 'size' is bigger than the available tailroom space. */
void *
dp_packet_put(struct dp_packet *b, const void *p, size_t size)
{
void *dst = dp_packet_put_uninit(b, size);
+ if (!dst) {
+ return NULL;
+ }
memcpy(dst, p, size);
return dst;
}
@@ -370,7 +429,9 @@ dp_packet_put_hex(struct dp_packet *b, const char *s, size_t *n)
return CONST_CAST(char *, s);
}
- dp_packet_put(b, &byte, 1);
+ if (!dp_packet_put(b, &byte, 1)) {
+ return NULL;
+ }
s += 2;
}
}
@@ -399,10 +460,19 @@ dp_packet_reserve_with_tailroom(struct dp_packet *b, size_t headroom,
/* Prefixes 'size' bytes to the head end of 'b', reallocating and copying its
* data if necessary. Returns a pointer to the first byte of the data's
- * location in the dp_packet. The new data is left uninitialized. */
+ * location in the dp_packet. The new data is left uninitialized.
+ * It may return NULL for DPDK packets, if 'size' is bigger than the available
+ * tailroom space
+ *
+ * For DPDK packets, no reallocation is performed and NULL may be returned if
+ * 'size' is bigger than the available headroom space. */
void *
dp_packet_push_uninit(struct dp_packet *b, size_t size)
{
+ if (!dp_packet_is_headroom_avail(b, size)) {
+ return NULL;
+ }
+
dp_packet_prealloc_headroom(b, size);
dp_packet_set_data(b, (char*)dp_packet_data(b) - size);
dp_packet_set_size(b, dp_packet_size(b) + size);
@@ -411,22 +481,34 @@ dp_packet_push_uninit(struct dp_packet *b, size_t size)
/* Prefixes 'size' zeroed bytes to the head end of 'b', reallocating and
* copying its data if necessary. Returns a pointer to the first byte of the
- * data's location in the dp_packet. */
+ * data's location in the dp_packet.
+ *
+ * For DPDK packets, no reallocation is performed and NULL may be returned if
+ * 'size' is bigger than the available headroom space. */
void *
dp_packet_push_zeros(struct dp_packet *b, size_t size)
{
void *dst = dp_packet_push_uninit(b, size);
+ if (!dst) {
+ return NULL;
+ }
memset(dst, 0, size);
return dst;
}
/* Copies the 'size' bytes starting at 'p' to the head end of 'b', reallocating
* and copying its data if necessary. Returns a pointer to the first byte of
- * the data's location in the dp_packet. */
+ * the data's location in the dp_packet.
+ *
+ * For DPDK packets, no reallocation is performed and NULL may be returned if
+ * 'size' is bigger than the available headroom space. */
void *
dp_packet_push(struct dp_packet *b, const void *p, size_t size)
{
void *dst = dp_packet_push_uninit(b, size);
+ if (!dst) {
+ return NULL;
+ }
memcpy(dst, p, size);
return dst;
}
@@ -463,12 +545,17 @@ dp_packet_adjust_layer_offset(uint16_t *offset, int increment)
/* Adjust the size of the l2_5 portion of the dp_packet, updating the l2
* pointer and the layer offsets. The caller is responsible for
- * modifying the contents. */
+ * modifying the contents.
+ *
+ * For DPDK packets, NULL may be returned if 'increment' is bigger than the
+ * available headroom space. */
void *
dp_packet_resize_l2_5(struct dp_packet *b, int increment)
{
if (increment >= 0) {
- dp_packet_push_uninit(b, increment);
+ if (!dp_packet_push_uninit(b, increment)) {
+ return NULL;
+ }
} else {
dp_packet_pull(b, -increment);
}
@@ -482,11 +569,16 @@ dp_packet_resize_l2_5(struct dp_packet *b, int increment)
/* Adjust the size of the l2 portion of the dp_packet, updating the l2
* pointer and the layer offsets. The caller is responsible for
- * modifying the contents. */
+ * modifying the contents.
+ *
+ * For DPDK packets, NULL may be returned if 'increment' is bigger than the
+ * available headroom space. */
void *
dp_packet_resize_l2(struct dp_packet *b, int increment)
{
- dp_packet_resize_l2_5(b, increment);
+ if (!dp_packet_resize_l2_5(b, increment)) {
+ return NULL;
+ }
dp_packet_adjust_layer_offset(&b->l2_5_ofs, increment);
return dp_packet_data(b);
}
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index 56baaa2..d1e0f5f 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -152,6 +152,10 @@ netdev_tnl_push_ip_header(struct dp_packet *packet,
struct ovs_16aligned_ip6_hdr *ip6;
eth = dp_packet_push_uninit(packet, size);
+ if (!eth) {
+ VLOG_WARN_RL(&err_rl, "failed to push ip header");
+ return NULL;
+ }
*ip_tot_size = dp_packet_size(packet) - sizeof (struct eth_header);
memcpy(eth, header, size);
@@ -214,7 +218,7 @@ udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
}
-void
+int
netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
@@ -223,6 +227,9 @@ netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED,
int ip_tot_size;
udp = netdev_tnl_push_ip_header(packet, data->header, data->header_len, &ip_tot_size);
+ if (!udp) {
+ return 1;
+ }
/* set udp src port */
udp->udp_src = netdev_tnl_get_src_port(packet);
@@ -243,6 +250,8 @@ netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED,
udp->udp_csum = htons(0xffff);
}
}
+
+ return 0;
}
static void *
@@ -435,7 +444,7 @@ err:
return NULL;
}
-void
+int
netdev_gre_push_header(const struct netdev *netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
@@ -446,6 +455,9 @@ netdev_gre_push_header(const struct netdev *netdev,
int ip_tot_size;
greh = netdev_tnl_push_ip_header(packet, data->header, data->header_len, &ip_tot_size);
+ if (!greh) {
+ return 1;
+ }
if (greh->flags & htons(GRE_CSUM)) {
ovs_be16 *csum_opt = (ovs_be16 *) (greh + 1);
@@ -460,6 +472,8 @@ netdev_gre_push_header(const struct netdev *netdev,
tnl_cfg = &dev->tnl_cfg;
put_16aligned_be32(seq_opt, htonl(tnl_cfg->seqno++));
}
+
+ return 0;
}
int
@@ -588,7 +602,7 @@ err:
return NULL;
}
-void
+int
netdev_erspan_push_header(const struct netdev *netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data)
@@ -602,6 +616,9 @@ netdev_erspan_push_header(const struct netdev *netdev,
greh = netdev_tnl_push_ip_header(packet, data->header,
data->header_len, &ip_tot_size);
+ if (!greh) {
+ return 1;
+ }
/* update GRE seqno */
tnl_cfg = &dev->tnl_cfg;
@@ -614,6 +631,7 @@ netdev_erspan_push_header(const struct netdev *netdev,
md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
put_16aligned_be32(&md2->timestamp, get_erspan_ts(ERSPAN_100US));
}
+ return 0;
}
int
diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h
index 5dc0012..7c36229 100644
--- a/lib/netdev-native-tnl.h
+++ b/lib/netdev-native-tnl.h
@@ -33,7 +33,7 @@ netdev_gre_build_header(const struct netdev *netdev,
struct ovs_action_push_tnl *data,
const struct netdev_tnl_build_header_params *params);
-void
+int
netdev_gre_push_header(const struct netdev *netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
@@ -45,14 +45,14 @@ netdev_erspan_build_header(const struct netdev *netdev,
struct ovs_action_push_tnl *data,
const struct netdev_tnl_build_header_params *p);
-void
+int
netdev_erspan_push_header(const struct netdev *netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
struct dp_packet *
netdev_erspan_pop_header(struct dp_packet *packet);
-void
+int
netdev_tnl_push_udp_header(const struct netdev *netdev,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 1a572f5..6c43a1f 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -314,7 +314,7 @@ struct netdev_class {
* flow. Push header is called for packet to build header specific to
* a packet on actual transmit. It uses partial header build by
* build_header() which is passed as data. */
- void (*push_header)(const struct netdev *,
+ int (*push_header)(const struct netdev *,
struct dp_packet *packet,
const struct ovs_action_push_tnl *data);
diff --git a/lib/netdev.c b/lib/netdev.c
index 82ffeb9..277b76d 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -857,9 +857,19 @@ netdev_push_header(const struct netdev *netdev,
const struct ovs_action_push_tnl *data)
{
struct dp_packet *packet;
- DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
- netdev->netdev_class->push_header(netdev, packet, data);
- pkt_metadata_init(&packet->md, data->out_port);
+ bool drop = false;
+ const size_t cnt = dp_packet_batch_size(batch);
+
+ size_t i;
+ DP_PACKET_BATCH_REFILL_FOR_EACH (i, cnt, packet, batch) {
+ drop = netdev->netdev_class->push_header(netdev, packet, data);
+ if (drop) {
+ dp_packet_delete(packet);
+ } else {
+ pkt_metadata_init(&packet->md, data->out_port);
+ /* Re-inject packet */
+ dp_packet_batch_refill(batch, packet, i);
+ }
}
return 0;
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 5831d1f..bfca79c 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -780,9 +780,17 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
case OVS_ACTION_ATTR_PUSH_VLAN: {
const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
- DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
- eth_push_vlan(packet, vlan->vlan_tpid, vlan->vlan_tci);
+ size_t i;
+ const size_t num = dp_packet_batch_size(batch);
+
+ DP_PACKET_BATCH_REFILL_FOR_EACH (i, num, packet, batch) {
+ if (!eth_push_vlan(packet, vlan->vlan_tpid, vlan->vlan_tci)) {
+ dp_packet_batch_refill(batch, packet, i);
+ } else {
+ dp_packet_delete(packet);
+ }
}
+
break;
}
@@ -795,9 +803,17 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
case OVS_ACTION_ATTR_PUSH_MPLS: {
const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
- DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
- push_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse);
+ size_t i;
+ const size_t num = dp_packet_batch_size(batch);
+
+ DP_PACKET_BATCH_REFILL_FOR_EACH (i, num, packet, batch) {
+ if (!push_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse)) {
+ dp_packet_batch_refill(batch, packet, i);
+ } else {
+ dp_packet_delete(packet);
+ }
}
+
break;
}
@@ -858,10 +874,18 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
case OVS_ACTION_ATTR_PUSH_ETH: {
const struct ovs_action_push_eth *eth = nl_attr_get(a);
- DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
- push_eth(packet, ð->addresses.eth_dst,
- ð->addresses.eth_src);
+ size_t i;
+ const size_t num = dp_packet_batch_size(batch);
+
+ DP_PACKET_BATCH_REFILL_FOR_EACH (i, num, packet, batch) {
+ if (!push_eth(packet, ð->addresses.eth_dst,
+ ð->addresses.eth_src)) {
+ dp_packet_batch_refill(batch, packet, i);
+ } else {
+ dp_packet_delete(packet);
+ }
}
+
break;
}
@@ -876,8 +900,15 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
struct nsh_hdr *nsh_hdr = ALIGNED_CAST(struct nsh_hdr *, buffer);
nsh_reset_ver_flags_ttl_len(nsh_hdr);
odp_nsh_hdr_from_attr(nl_attr_get(a), nsh_hdr, NSH_HDR_MAX_LEN);
- DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
- push_nsh(packet, nsh_hdr);
+ size_t i;
+ const size_t num = dp_packet_batch_size(batch);
+
+ DP_PACKET_BATCH_REFILL_FOR_EACH (i, num, packet, batch) {
+ if (!push_nsh(packet, nsh_hdr)) {
+ dp_packet_batch_refill(batch, packet, i);
+ } else {
+ dp_packet_delete(packet);
+ }
}
break;
}
diff --git a/lib/packets.c b/lib/packets.c
index 38bfb60..9f6282c 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -34,6 +34,10 @@
#include "odp-util.h"
#include "dp-packet.h"
#include "unaligned.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(packets);
+static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5);
const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT;
const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT;
@@ -210,16 +214,22 @@ compose_rarp(struct dp_packet *b, const struct eth_addr eth_src)
* packet. Ignores the CFI bit of 'tci' using 0 instead.
*
* Also adjusts the layer offsets accordingly. */
-void
+int
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);
+ if (!veh) {
+ VLOG_WARN_RL(&err_rl, "failed to push vlan header");
+ return 1;
+ }
memmove(veh, (char *)veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN);
veh->veth_type = tpid;
veh->veth_tci = tci & htons(~VLAN_CFI);
+
+ return 0;
}
/* Removes outermost VLAN header (if any is present) from 'packet'.
@@ -240,7 +250,7 @@ eth_pop_vlan(struct dp_packet *packet)
}
/* Push Ethernet header onto 'packet' assuming it is layer 3 */
-void
+int
push_eth(struct dp_packet *packet, const struct eth_addr *dst,
const struct eth_addr *src)
{
@@ -248,10 +258,16 @@ push_eth(struct dp_packet *packet, const struct eth_addr *dst,
ovs_assert(packet->packet_type != htonl(PT_ETH));
eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);
+ if (!eh) {
+ VLOG_WARN_RL(&err_rl, "failed to push eth header");
+ return 1;
+ }
eh->eth_dst = *dst;
eh->eth_src = *src;
eh->eth_type = pt_ns_type_be(packet->packet_type);
packet->packet_type = htonl(PT_ETH);
+
+ return 0;
}
/* Removes Ethernet header, including VLAN header, from 'packet'.
@@ -369,14 +385,14 @@ set_mpls_lse(struct dp_packet *packet, ovs_be32 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
+int
push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse)
{
char * header;
size_t len;
if (!eth_type_mpls(ethtype)) {
- return;
+ return 0;
}
if (!is_mpls(packet)) {
@@ -389,8 +405,14 @@ push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse)
/* Push new MPLS shim header onto packet. */
len = packet->l2_5_ofs;
header = dp_packet_resize_l2_5(packet, MPLS_HLEN);
+ if (!header) {
+ VLOG_WARN_RL(&err_rl, "failed to push mpls header");
+ return 1;
+ }
memmove(header, header + MPLS_HLEN, len);
memcpy(header + len, &lse, sizeof lse);
+
+ return 0;
}
/* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry.
@@ -414,7 +436,7 @@ pop_mpls(struct dp_packet *packet, ovs_be16 ethtype)
}
}
-void
+int
push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src)
{
struct nsh_hdr *nsh;
@@ -439,11 +461,17 @@ push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src)
}
nsh = (struct nsh_hdr *) dp_packet_push_uninit(packet, length);
+ if (!nsh) {
+ VLOG_WARN_RL(&err_rl, "failed to push nsh header");
+ return 1;
+ }
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;
+
+ return 0;
}
bool
diff --git a/lib/packets.h b/lib/packets.h
index 7645a9d..d8c0795 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -330,7 +330,7 @@ bool eth_addr_from_string(const char *, struct eth_addr *);
void compose_rarp(struct dp_packet *, const struct eth_addr);
-void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci);
+int 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);
@@ -338,7 +338,7 @@ void eth_format_masked(const struct eth_addr ea,
const struct eth_addr *mask, struct ds *s);
void set_mpls_lse(struct dp_packet *, ovs_be32 label);
-void push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse);
+int push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse);
void pop_mpls(struct dp_packet *, ovs_be16 ethtype);
void set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl);
@@ -438,11 +438,11 @@ struct eth_header {
};
BUILD_ASSERT_DECL(ETH_HEADER_LEN == sizeof(struct eth_header));
-void push_eth(struct dp_packet *packet, const struct eth_addr *dst,
+int 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);
+int push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src);
bool pop_nsh(struct dp_packet *packet);
#define LLC_DSAP_SNAP 0xaa
--
2.7.4
More information about the dev
mailing list