[ovs-dev] [PATCH 4/4] User-Space MPLS actions and matches
Simon Horman
horms at verge.net.au
Mon Oct 15 05:37:04 UTC 2012
On Thu, Oct 11, 2012 at 11:14:40AM +0900, Simon Horman wrote:
[snip]
> Below is a revised version of the patch which:
>
> * Addresses the concerns you raise above, other
> than the default Ethertype for push_mpls()
> * Incorporates the user-space datapath code as there
> seem to be mutual dependencies between that and
> the other user-space code.
>
> I have pushed this and much more minor changes to the other
> patches in the series to the devel/mpls branch of
> git://github.com/horms/openvswitch.git
> (HEAD = 8b8c4af22ba5c1bddd1dc455fd8a5820cc3e2812)
>
> I would repost the entire series, but as you haven't completed
> your review of this patch I thought it would be best to just
> post an update inline.
In the course of adding code to track the MPLS stack depth,
as suggested by Yamahata-san, I found some problems which
I have noted inline.
>
> ----------------------------------------------------------------
>
> From: Simon Horman <horms at verge.net.au>
>
> 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: Isaku Yamahata <yamahata at valinux.co.jp>
> Cc: Ravi K <rkerur at gmail.com>
> Signed-off-by: Simon Horman <horms at verge.net.au>
[snip]
> diff --git a/lib/flow.c b/lib/flow.c
> index 76d2340..5291e19 100644
> --- a/lib/flow.c
> +++ b/lib/flow.c
> @@ -93,6 +93,28 @@ pull_icmpv6(struct ofpbuf *packet)
> }
>
> static void
> +parse_remaining_mpls(struct ofpbuf *b)
> +{
> + /* Proceed with parsing remaining MPLS headers. */
> + struct mpls_hdr *mh;
> + while ((mh = ofpbuf_try_pull(b, sizeof *mh)) &&
> + (mh->mpls_lse & htonl(MPLS_BOS_MASK))) {
> + ;
> + }
> +}
I believe the logic above is (still!) wrong. I think that the
BoS check should be inverted yielding.
static void
parse_remaining_mpls(struct ofpbuf *b, struct flow *flow)
{
/* Proceed with parsing remaining MPLS headers. */
struct mpls_hdr *mh;
while ((mh = ofpbuf_try_pull(b, sizeof *mh)) &&
!(mh->mpls_lse & htonl(MPLS_BOS_MASK))) {
flow->mpls_depth++;
}
}
[snip]
> diff --git a/lib/packets.c b/lib/packets.c
> index 16f4fe6..0b85cf9 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
[snip]
> @@ -211,6 +212,361 @@ eth_pop_vlan(struct ofpbuf *packet)
[snip]
The dec_mpls_ttl(), copy_mpls_ttl_in() and copy_mpls_ttl_out() functions
below are not used by this patchset and I will remove them from the next
revision of this patch.
> +
> +/* Decrement MPLS TTL from the packet.
> + * 'packet->l2_5' must initially point to 'packet''s MPLS Label stack. */
> +void
> +dec_mpls_ttl(struct ofpbuf *packet, uint8_t new_ttl)
> +{
> + ovs_be16 eth_type = htons(0);
> + struct eth_header *eh = packet->data;
> + struct mpls_hdr *mh = packet->l2_5;
> +
> + if (packet->size < sizeof *eh) {
> + return;
> + }
> +
> + /* Packet type should be mpls to decrement ttl. */
> + eth_type = get_ethertype(packet);
> +
> + if (eth_type == htons(ETH_TYPE_MPLS) ||
> + eth_type == htons(ETH_TYPE_MPLS_MCAST)) {
> +
> + /* Update decremented ttl into mpls header. */
> + set_mpls_lse_ttl(&mh->mpls_lse, htonl(new_ttl << MPLS_TTL_SHIFT));
> + }
> +}
> +
> +/* Copy MPLS TTL from the packet either ipv4/ipv6.
> + * 'packet->l2_5' must initially point to 'packet''s MPLS Label stack. */
> +void
> +copy_mpls_ttl_in(struct ofpbuf *packet, uint8_t new_ttl)
> +{
> + struct eth_header *eh = packet->data;
> + struct mpls_hdr *mh = packet->l2_5;
> + struct ip_header *ih = packet->l3;
> + struct ip6_hdr *ih6 = packet->l3;
> + ovs_be16 eth_type = htons(0);
> + size_t hdr_size = sizeof *eh + sizeof *mh + sizeof *ih;
> +
> + if (packet->size < hdr_size) {
> + return;
> + }
> +
> + /* Packet type should be mpls to copy ttl to l3. */
> + eth_type = get_ethertype(packet);
> + if (eth_type == htons(ETH_TYPE_MPLS) ||
> + eth_type == htons(ETH_TYPE_MPLS_MCAST)) {
> +
> + /* If bottom of the stack handle IP checksum. */
> + if (mh->mpls_lse & htonl(MPLS_BOS_MASK)) {
> + if (IP_VER(ih->ip_ihl_ver) == IP_VERSION) {
> + /* Change the ip checksum. */
> + uint8_t *field = &ih->ip_ttl;
> + ih->ip_csum = recalc_csum16(ih->ip_csum,
> + htons(*field << 8), htons(new_ttl << 8));
> + ih->ip_ttl = new_ttl;
> + } else if (IP6_VER(ih6->ip6_vfc) == IP6_VERSION) {
> + ih6->ip6_hlim = new_ttl;
> + }
> + } else {
> + struct mpls_hdr *mh2;
> + mh2 = (struct mpls_hdr *)((char *) packet->l2_5 + sizeof *mh);
> + set_mpls_lse_ttl(&mh2->mpls_lse, htonl(new_ttl << MPLS_TTL_SHIFT));
> + }
> + }
> +}
> +
> +/* Copy MPLS TTL to the packet layer3 only ipv4/ipv6.
> + * 'packet->l2_5' must initially point to 'packet''s MPLS Label stack. */
> +void
> +copy_mpls_ttl_out(struct ofpbuf *packet, uint8_t new_ttl)
> +{
> + struct eth_header *eh = packet->data;
> + struct mpls_hdr *mh = packet->l2_5;
> + struct ip_header *ih = packet->l3;
> + struct ip6_hdr *ih6 = packet->l3;
> + ovs_be16 eth_type = htons(0);
> + size_t hdr_size = sizeof *eh + sizeof *mh + sizeof *ih;
> +
> + /* TTL sent from ofproto-dpif.c is not the correct one,
> + * hence ignore it. */
> + if (packet->size < hdr_size) {
> + return;
> + }
> +
> + /* Packet type should me mpls to copy ttl from l3. */
> + eth_type = get_ethertype(packet);
> + if (eth_type == htons(ETH_TYPE_MPLS) ||
> + eth_type == htons(ETH_TYPE_MPLS_MCAST)) {
> +
> + /* If bottom of the stack copy from l3. */
> + if (mh->mpls_lse & htonl(MPLS_BOS_MASK)) {
> + uint8_t nh_ttl;
> + /* Get ipv4 or ipv6 or default ttl. */
> + if (IP_VER(ih->ip_ihl_ver) == IP_VERSION) {
> + nh_ttl = ih->ip_ttl;
> + } else if (IP6_VER(ih6->ip6_vfc) == IP6_VERSION) {
> + nh_ttl = ih6->ip6_hlim;
> + } else {
> + nh_ttl = 64; /* Default ttl for non-IP. */
> + }
> + set_mpls_lse_ttl(&mh->mpls_lse, htonl(nh_ttl << MPLS_TTL_SHIFT));
> + } else {
> + struct mpls_hdr *mh2;
> + mh2 = (struct mpls_hdr *)((char *) packet->l2_5 + sizeof *mh);
> + new_ttl = mpls_lse_to_ttl(mh2->mpls_lse);
> + set_mpls_lse_ttl(&mh->mpls_lse, htonl(new_ttl << MPLS_TTL_SHIFT));
> + }
> + }
> +}
[snip]
More information about the dev
mailing list