2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

User-Space MPLS actions and matches

This patch implements use-space datapath and non-datapath code
to match and use the datapath API set out in Leo Alterman's patch
"user-space datapath: Add basic MPLS support to kernel".

The resulting MPLS implementation supports:
* Pushing a single MPLS label
* Poping a single MPLS label
* Modifying an MPLS lable using set-field or load actions
  that act on the label value, tc and bos bit.
* There is no support for manipulating the TTL
  this is considered future work.

The single-level push pop limitation is implemented by processing
push, pop and set-field/load actions in order and discarding information
that would require multiple levels of push/pop to be supported.

e.g.
   push,push -> the first push is discarded
   pop,pop -> the first pop is discarded

This patch is based heavily on work by Ravi K.

Cc: Ravi K <rkerur@gmail.com>
Reviewed-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Simon Horman
2013-01-25 16:22:07 +09:00
committed by Ben Pfaff
parent d224e35014
commit b02475c53b
29 changed files with 1223 additions and 61 deletions

View File

@@ -140,6 +140,10 @@ void compose_rarp(struct ofpbuf *, const uint8_t eth_src[ETH_ADDR_LEN]);
void eth_push_vlan(struct ofpbuf *, ovs_be16 tci);
void eth_pop_vlan(struct ofpbuf *);
uint16_t eth_mpls_depth(const struct ofpbuf *packet);
void set_ethertype(struct ofpbuf *packet, ovs_be16 eth_type);
const char *eth_from_hex(const char *hex, struct ofpbuf **packetp);
void eth_format_masked(const uint8_t eth[ETH_ADDR_LEN],
const uint8_t mask[ETH_ADDR_LEN], struct ds *s);
@@ -147,6 +151,16 @@ void eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
const uint8_t mask[ETH_ADDR_LEN],
uint8_t dst[ETH_ADDR_LEN]);
void set_mpls_lse(struct ofpbuf *, ovs_be32 label);
void push_mpls(struct ofpbuf *packet, ovs_be16 ethtype, ovs_be32 lse);
void pop_mpls(struct ofpbuf *, ovs_be16 ethtype);
void set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc);
void set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label);
void set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos);
ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos,
ovs_be32 label);
/* Example:
*
* uint8_t mac[ETH_ADDR_LEN];
@@ -186,6 +200,12 @@ void eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
#define ETH_TYPE_MPLS 0x8847
#define ETH_TYPE_MPLS_MCAST 0x8848
static inline bool eth_type_mpls(ovs_be16 eth_type)
{
return eth_type == htons(ETH_TYPE_MPLS) ||
eth_type == htons(ETH_TYPE_MPLS_MCAST);
}
/* Minimum value for an Ethernet type. Values below this are IEEE 802.2 frame
* lengths. */
#define ETH_TYPE_MIN 0x600
@@ -272,6 +292,66 @@ struct vlan_eth_header {
} __attribute__((packed));
BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header));
/* MPLS related definitions */
#define MPLS_TTL_MASK 0x000000ff
#define MPLS_TTL_SHIFT 0
#define MPLS_BOS_MASK 0x00000100
#define MPLS_BOS_SHIFT 8
#define MPLS_TC_MASK 0x00000e00
#define MPLS_TC_SHIFT 9
#define MPLS_LABEL_MASK 0xfffff000
#define MPLS_LABEL_SHIFT 12
#define MPLS_HLEN 4
struct mpls_hdr {
ovs_be32 mpls_lse;
};
BUILD_ASSERT_DECL(MPLS_HLEN == sizeof(struct mpls_hdr));
/* Given a mpls label stack entry in network byte order
* return mpls label in host byte order */
static inline uint32_t
mpls_lse_to_label(ovs_be32 mpls_lse)
{
return (ntohl(mpls_lse) & MPLS_LABEL_MASK) >> MPLS_LABEL_SHIFT;
}
/* Given a mpls label stack entry in network byte order
* return mpls tc */
static inline uint8_t
mpls_lse_to_tc(ovs_be32 mpls_lse)
{
return (ntohl(mpls_lse) & MPLS_TC_MASK) >> MPLS_TC_SHIFT;
}
/* Given a mpls label stack entry in network byte order
* return mpls ttl */
static inline uint8_t
mpls_lse_to_ttl(ovs_be32 mpls_lse)
{
return (ntohl(mpls_lse) & MPLS_TTL_MASK) >> MPLS_TTL_SHIFT;
}
/* Set TTL in mpls lse. */
static inline void
flow_set_mpls_lse_ttl(ovs_be32 *mpls_lse, uint8_t ttl)
{
*mpls_lse &= ~htonl(MPLS_TTL_MASK);
*mpls_lse |= htonl(ttl << MPLS_TTL_SHIFT);
}
/* Given a mpls label stack entry in network byte order
* return mpls BoS bit */
static inline uint8_t
mpls_lse_to_bos(ovs_be32 mpls_lse)
{
return (mpls_lse & htonl(MPLS_BOS_MASK)) != 0;
}
#define IP_FMT "%"PRIu32".%"PRIu32".%"PRIu32".%"PRIu32
#define IP_ARGS(ip) \
ntohl(ip) >> 24, \