]> git.proxmox.com Git - ovs.git/commitdiff
Merge tag '2.9.2' into master-dfsg
authorThomas Goirand <zigo@debian.org>
Thu, 30 Aug 2018 07:32:30 +0000 (09:32 +0200)
committerThomas Goirand <zigo@debian.org>
Thu, 30 Aug 2018 07:32:30 +0000 (09:32 +0200)
Open vSwitch version 2.9.2

1  2 
NEWS
datapath/linux/compat/include/linux/openvswitch.h
include/openvswitch/packets.h
lib/conntrack.c
lib/meta-flow.xml
lib/netdev.c
lib/odp-util.c
ofproto/ofproto-dpif-xlate.c

diff --cc NEWS
Simple merge
Simple merge
diff --cc lib/conntrack.c
index ab250965d03d8ca6097d5837cf6c35daf2442242,562e767833d1bdeb3006f3def3d3b87d01ac5b36..c5cd1a913529609b7b4333c10cef2d4f6ec9d2ad
@@@ -387,10 -414,11 +413,12 @@@ write_ct_md(struct dp_packet *pkt, uint
          pkt->md.ct_label = alg_exp->master_label;
          key = &alg_exp->master_key;
      }
      pkt->md.ct_orig_tuple_ipv6 = false;
      if (key) {
          if (key->dl_type == htons(ETH_TYPE_IP)) {
 +
              pkt->md.ct_orig_tuple.ipv4 = (struct ovs_key_ct_tuple_ipv4) {
                  key->src.addr.ipv4_aligned,
                  key->dst.addr.ipv4_aligned,
@@@ -789,14 -858,15 +858,18 @@@ conn_not_found(struct conntrack *ct, st
          pkt->md.ct_state = CS_INVALID;
          return nc;
      }
      pkt->md.ct_state = CS_NEW;
 +    if (alg_exp) {
 +        pkt->md.ct_state |= CS_RELATED;
 +    }
  
+     if (alg_exp) {
+         pkt->md.ct_state |= CS_RELATED;
+     }
      if (commit) {
          unsigned int n_conn_limit;
          atomic_read_relaxed(&ct->n_conn_limit, &n_conn_limit);
  
          if (atomic_count_get(&ct->n_conn) >= n_conn_limit) {
Simple merge
diff --cc lib/netdev.c
index b4e570bafd08533d22d4f61f1af8bbeadff4bea1,be05dc64024a591535c953114d7a76257c74e500..fc7f75f029cdc36546b12c132c35787cf0d98018
@@@ -2264,32 -2272,11 +2272,32 @@@ netdev_ports_remove(odp_port_t port_no
      ovs_mutex_lock(&netdev_hmap_mutex);
  
      data = netdev_ports_lookup(port_no, dpif_class);
      if (data) {
 +        int ifindex = netdev_get_ifindex(data->netdev);
 +
 +        if (ifindex > 0) {
 +            struct ifindex_to_port_data *ifidx = NULL;
 +
 +            HMAP_FOR_EACH_WITH_HASH (ifidx, node, ifindex, &ifindex_to_port) {
 +                if (ifidx->port == port_no) {
 +                    hmap_remove(&ifindex_to_port, &ifidx->node);
 +                    free(ifidx);
 +                    break;
 +                }
 +            }
 +            ovs_assert(ifidx);
 +        } else {
 +            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 +
 +            VLOG_WARN_RL(&rl, "netdev ports map has dpif port %"PRIu32
 +                         " but netdev has no ifindex: %s", port_no,
 +                         ovs_strerror(ifindex));
 +        }
 +
          dpif_port_destroy(&data->dpif_port);
          netdev_close(data->netdev); /* unref and possibly close */
-         hmap_remove(&port_to_netdev, &data->node);
+         hmap_remove(&port_to_netdev, &data->portno_node);
+         hmap_remove(&ifindex_to_port, &data->ifindex_node);
          free(data);
          ret = 0;
      }
diff --cc lib/odp-util.c
index 13e17c62b6d3f3255c7ef7a145c01091f873ff69,4523b6cea5efdeb2201c23bc3ac40a884023f0f9..ae133f0603403d3f69b5adc66d403ab6489e4f93
@@@ -1780,113 -1897,159 +1897,266 @@@ find_end
      return s - s_;
  }
  
+ static void
+ nsh_key_to_attr(struct ofpbuf *buf, const struct ovs_key_nsh *nsh,
+                 uint8_t * metadata, size_t md_size,
+                 bool is_mask)
+ {
+     size_t nsh_key_ofs;
+     struct ovs_nsh_key_base base;
+     base.flags = nsh->flags;
+     base.ttl = nsh->ttl;
+     base.mdtype = nsh->mdtype;
+     base.np = nsh->np;
+     base.path_hdr = nsh->path_hdr;
+     nsh_key_ofs = nl_msg_start_nested(buf, OVS_KEY_ATTR_NSH);
+     nl_msg_put_unspec(buf, OVS_NSH_KEY_ATTR_BASE, &base, sizeof base);
+     if (is_mask) {
+         nl_msg_put_unspec(buf, OVS_NSH_KEY_ATTR_MD1, nsh->context,
+                           sizeof nsh->context);
+     } else {
+         switch (nsh->mdtype) {
+         case NSH_M_TYPE1:
+             nl_msg_put_unspec(buf, OVS_NSH_KEY_ATTR_MD1, nsh->context,
+                               sizeof nsh->context);
+             break;
+         case NSH_M_TYPE2:
+             if (metadata && md_size > 0) {
+                 nl_msg_put_unspec(buf, OVS_NSH_KEY_ATTR_MD2, metadata,
+                                   md_size);
+             }
+             break;
+         default:
+             /* No match support for other MD formats yet. */
+             break;
+         }
+     }
+     nl_msg_end_nested(buf, nsh_key_ofs);
+ }
+ static int
+ parse_odp_push_nsh_action(const char *s, struct ofpbuf *actions)
+ {
+     int n = 0;
+     int ret = 0;
+     uint32_t spi = 0;
+     uint8_t si = 255;
+     uint32_t cd;
+     struct ovs_key_nsh nsh;
+     uint8_t metadata[NSH_CTX_HDRS_MAX_LEN];
+     uint8_t md_size = 0;
+     if (!ovs_scan_len(s, &n, "push_nsh(")) {
+         ret = -EINVAL;
+         goto out;
+     }
+     /* The default is NSH_M_TYPE1 */
+     nsh.flags = 0;
+     nsh.ttl = 63;
+     nsh.mdtype = NSH_M_TYPE1;
+     nsh.np = NSH_P_ETHERNET;
+     nsh.path_hdr = nsh_spi_si_to_path_hdr(0, 255);
+     memset(nsh.context, 0, NSH_M_TYPE1_MDLEN);
+     for (;;) {
+         n += strspn(s + n, delimiters);
+         if (s[n] == ')') {
+             break;
+         }
+         if (ovs_scan_len(s, &n, "flags=%"SCNi8, &nsh.flags)) {
+             continue;
+         }
+         if (ovs_scan_len(s, &n, "ttl=%"SCNi8, &nsh.ttl)) {
+             continue;
+         }
+         if (ovs_scan_len(s, &n, "mdtype=%"SCNi8, &nsh.mdtype)) {
+             switch (nsh.mdtype) {
+             case NSH_M_TYPE1:
+                 /* This is the default format. */;
+                 break;
+             case NSH_M_TYPE2:
+                 /* Length will be updated later. */
+                 md_size = 0;
+                 break;
+             default:
+                 ret = -EINVAL;
+                 goto out;
+             }
+             continue;
+         }
+         if (ovs_scan_len(s, &n, "np=%"SCNi8, &nsh.np)) {
+             continue;
+         }
+         if (ovs_scan_len(s, &n, "spi=0x%"SCNx32, &spi)) {
+             continue;
+         }
+         if (ovs_scan_len(s, &n, "si=%"SCNi8, &si)) {
+             continue;
+         }
+         if (nsh.mdtype == NSH_M_TYPE1) {
+             if (ovs_scan_len(s, &n, "c1=0x%"SCNx32, &cd)) {
+                 nsh.context[0] = htonl(cd);
+                 continue;
+             }
+             if (ovs_scan_len(s, &n, "c2=0x%"SCNx32, &cd)) {
+                 nsh.context[1] = htonl(cd);
+                 continue;
+             }
+             if (ovs_scan_len(s, &n, "c3=0x%"SCNx32, &cd)) {
+                 nsh.context[2] = htonl(cd);
+                 continue;
+             }
+             if (ovs_scan_len(s, &n, "c4=0x%"SCNx32, &cd)) {
+                 nsh.context[3] = htonl(cd);
+                 continue;
+             }
+         }
+         else if (nsh.mdtype == NSH_M_TYPE2) {
+             struct ofpbuf b;
+             char buf[512];
+             size_t mdlen, padding;
+             if (ovs_scan_len(s, &n, "md2=0x%511[0-9a-fA-F]", buf)) {
+                 ofpbuf_use_stub(&b, metadata,
+                                 NSH_CTX_HDRS_MAX_LEN);
+                 ofpbuf_put_hex(&b, buf, &mdlen);
+                 /* Pad metadata to 4 bytes. */
+                 padding = PAD_SIZE(mdlen, 4);
+                 if (padding > 0) {
+                     ofpbuf_push_zeros(&b, padding);
+                 }
+                 md_size = mdlen + padding;
+                 ofpbuf_uninit(&b);
+                 continue;
+             }
+         }
+         ret = -EINVAL;
+         goto out;
+     }
+ out:
+     if (ret >= 0) {
+         nsh.path_hdr = nsh_spi_si_to_path_hdr(spi, si);
+         size_t offset = nl_msg_start_nested(actions, OVS_ACTION_ATTR_PUSH_NSH);
+         nsh_key_to_attr(actions, &nsh, metadata, md_size, false);
+         nl_msg_end_nested(actions, offset);
+         ret = n;
+     }
+     return ret;
+ }
 +static int
 +parse_odp_encap_nsh_action(const char *s, struct ofpbuf *actions)
 +{
 +    int n = 0;
 +    int ret = 0;
 +    struct ovs_action_encap_nsh encap_nsh;
 +    uint32_t spi;
 +    uint8_t si;
 +    uint32_t cd;
 +
 +    if (!ovs_scan_len(s, &n, "encap_nsh(")) {
 +        ret = -EINVAL;
 +        goto out;
 +    }
 +
 +    /* The default is NSH_M_TYPE1 */
 +    encap_nsh.flags = 0;
 +    encap_nsh.mdtype = NSH_M_TYPE1;
 +    encap_nsh.mdlen = NSH_M_TYPE1_MDLEN;
 +    encap_nsh.path_hdr = htonl(255);
 +    memset(encap_nsh.metadata, 0, NSH_M_TYPE1_MDLEN);
 +
 +    for (;;) {
 +        n += strspn(s + n, delimiters);
 +        if (s[n] == ')') {
 +            break;
 +        }
 +
 +        if (ovs_scan_len(s, &n, "flags=%"SCNi8, &encap_nsh.flags)) {
 +            continue;
 +        }
 +        if (ovs_scan_len(s, &n, "mdtype=%"SCNi8, &encap_nsh.mdtype)) {
 +            switch (encap_nsh.mdtype) {
 +            case NSH_M_TYPE1:
 +                /* This is the default format. */;
 +                break;
 +            case NSH_M_TYPE2:
 +                /* Length will be updated later. */
 +                encap_nsh.mdlen = 0;
 +                break;
 +            default:
 +                ret = -EINVAL;
 +                goto out;
 +            }
 +            continue;
 +        }
 +        if (ovs_scan_len(s, &n, "np=%"SCNi8, &encap_nsh.np)) {
 +            continue;
 +        }
 +        if (ovs_scan_len(s, &n, "spi=0x%"SCNx32, &spi)) {
 +            encap_nsh.path_hdr =
 +                    htonl(((spi << NSH_SPI_SHIFT) & NSH_SPI_MASK) |
 +                            (ntohl(encap_nsh.path_hdr) & ~NSH_SPI_MASK));
 +            continue;
 +        }
 +        if (ovs_scan_len(s, &n, "si=%"SCNi8, &si)) {
 +            encap_nsh.path_hdr =
 +                    htonl((si << NSH_SI_SHIFT) |
 +                            (ntohl(encap_nsh.path_hdr) & ~NSH_SI_MASK));
 +            continue;
 +        }
 +        if (encap_nsh.mdtype == NSH_M_TYPE1) {
 +            struct nsh_md1_ctx *md1 =
 +                ALIGNED_CAST(struct nsh_md1_ctx *, encap_nsh.metadata);
 +            if (ovs_scan_len(s, &n, "c1=0x%"SCNx32, &cd)) {
 +                put_16aligned_be32(&md1->c[0], htonl(cd));
 +                continue;
 +            }
 +            if (ovs_scan_len(s, &n, "c2=0x%"SCNx32, &cd)) {
 +                put_16aligned_be32(&md1->c[1], htonl(cd));
 +                continue;
 +            }
 +            if (ovs_scan_len(s, &n, "c3=0x%"SCNx32, &cd)) {
 +                put_16aligned_be32(&md1->c[2], htonl(cd));
 +                continue;
 +            }
 +            if (ovs_scan_len(s, &n, "c4=0x%"SCNx32, &cd)) {
 +                put_16aligned_be32(&md1->c[3], htonl(cd));
 +                continue;
 +            }
 +        }
 +        else if (encap_nsh.mdtype == NSH_M_TYPE2) {
 +            struct ofpbuf b;
 +            char buf[512];
 +            size_t mdlen;
 +            if (ovs_scan_len(s, &n, "md2=0x%511[0-9a-fA-F]", buf)) {
 +                ofpbuf_use_stub(&b, encap_nsh.metadata,
 +                                OVS_ENCAP_NSH_MAX_MD_LEN);
 +                ofpbuf_put_hex(&b, buf, &mdlen);
 +                encap_nsh.mdlen = mdlen;
 +                ofpbuf_uninit(&b);
 +            }
 +            continue;
 +        }
 +    }
 +out:
 +    if (ret < 0) {
 +        return ret;
 +    } else {
 +        size_t size = offsetof(struct ovs_action_encap_nsh, metadata)
 +                + ROUND_UP(encap_nsh.mdlen, 4);
 +        nl_msg_put_unspec(actions, OVS_ACTION_ATTR_ENCAP_NSH,
 +                          &encap_nsh, size);
 +        return n;
 +    }
 +}
 +
  static int
  parse_action_list(const char *s, const struct simap *port_names,
                    struct ofpbuf *actions)
index 973e760547fad9feede302e85254e2425947af6c,8b9405ad60ad0deac25712efb4a5a39e296fa877..bc1ed10e7c8dacb32e64f093448aa49f3d186e72
@@@ -5798,120 -5789,121 +5789,231 @@@ rewrite_flow_encap_ethernet(struct xlat
          xlate_report_debug(ctx, OFT_ACTION,
                             "Dropping packet as encap(ethernet) is not "
                             "supported for packet type ethernet.");
-         ctx->error = 1;
+         ctx->error = XLATE_UNSUPPORTED_PACKET_TYPE;
+     }
+ }
+ /* For an MD2 NSH header returns a pointer to an ofpbuf with the encoded
+  * MD2 TLVs provided as encap properties to the encap operation. This
+  * will be stored as encap_data in the ctx and copied into the push_nsh
+  * action at the next commit. */
+ static struct ofpbuf *
+ rewrite_flow_push_nsh(struct xlate_ctx *ctx,
+                       const struct ofpact_encap *encap,
+                       struct flow *flow,
+                       struct flow_wildcards *wc)
+ {
+     ovs_be32 packet_type = flow->packet_type;
+     const char *ptr = (char *) encap->props;
+     struct ofpbuf *buf = ofpbuf_new(NSH_CTX_HDRS_MAX_LEN);
+     uint8_t md_type = NSH_M_TYPE1;
+     uint8_t np = 0;
+     int i;
+     /* Scan the optional NSH encap TLV properties, if any. */
+     for (i = 0; i < encap->n_props; i++) {
+         struct ofpact_ed_prop *prop_ptr =
+             ALIGNED_CAST(struct ofpact_ed_prop *, ptr);
+         if (prop_ptr->prop_class == OFPPPC_NSH) {
+             switch (prop_ptr->type) {
+                 case OFPPPT_PROP_NSH_MDTYPE: {
+                     struct ofpact_ed_prop_nsh_md_type *prop_md_type =
+                         ALIGNED_CAST(struct ofpact_ed_prop_nsh_md_type *,
+                                      prop_ptr);
+                     md_type = prop_md_type->md_type;
+                     break;
+                 }
+                 case OFPPPT_PROP_NSH_TLV: {
+                     struct ofpact_ed_prop_nsh_tlv *tlv_prop =
+                         ALIGNED_CAST(struct ofpact_ed_prop_nsh_tlv *,
+                                      prop_ptr);
+                     struct nsh_md2_tlv *md2_ctx =
+                             ofpbuf_put_uninit(buf, sizeof(*md2_ctx));
+                     md2_ctx->md_class = tlv_prop->tlv_class;
+                     md2_ctx->type = tlv_prop->tlv_type;
+                     md2_ctx->length = tlv_prop->tlv_len;
+                     size_t len = ROUND_UP(md2_ctx->length, 4);
+                     size_t padding = len - md2_ctx->length;
+                     ofpbuf_put(buf, tlv_prop->data, md2_ctx->length);
+                     ofpbuf_put_zeros(buf, padding);
+                     break;
+                 }
+                 default:
+                     /* No other NSH encap properties defined yet. */
+                     break;
+             }
+         }
+         ptr += ROUND_UP(prop_ptr->len, 8);
+     }
+     if (buf->size == 0 || buf->size > NSH_CTX_HDRS_MAX_LEN) {
+         ofpbuf_delete(buf);
+         buf = NULL;
      }
+     /* Determine the Next Protocol field for NSH header. */
+     switch (ntohl(packet_type)) {
+         case PT_ETH:
+             np = NSH_P_ETHERNET;
+             break;
+         case PT_IPV4:
+             np = NSH_P_IPV4;
+             break;
+         case PT_IPV6:
+             np = NSH_P_IPV6;
+             break;
+         case PT_NSH:
+             np = NSH_P_NSH;
+             break;
+         default:
+             /* Error handling: drop packet. */
+             xlate_report_debug(ctx, OFT_ACTION,
+                                "Dropping packet as encap(nsh) is not "
+                                "supported for packet type (%d,0x%x)",
+                                pt_ns(packet_type), pt_ns_type(packet_type));
+             ctx->error = XLATE_UNSUPPORTED_PACKET_TYPE;
+             return buf;
+     }
+     /* Note that we have matched on packet_type! */
+     wc->masks.packet_type = OVS_BE32_MAX;
+     /* Reset all current flow packet headers. */
+     memset(&flow->dl_dst, 0,
+            sizeof(struct flow) - offsetof(struct flow, dl_dst));
+     /* Populate the flow with the new NSH header. */
+     flow->packet_type = htonl(PT_NSH);
+     flow->dl_type = htons(ETH_TYPE_NSH);
+     flow->nsh.flags = 0;
+     flow->nsh.ttl = 63;
+     flow->nsh.np = np;
+     flow->nsh.path_hdr = htonl(255);
+     if (md_type == NSH_M_TYPE1) {
+         flow->nsh.mdtype = NSH_M_TYPE1;
+         memset(flow->nsh.context, 0, sizeof flow->nsh.context);
+         if (buf) {
+             /* Drop any MD2 context TLVs. */
+             ofpbuf_delete(buf);
+             buf = NULL;
+         }
+     } else if (md_type == NSH_M_TYPE2) {
+         flow->nsh.mdtype = NSH_M_TYPE2;
+     }
+     flow->nsh.mdtype &= NSH_MDTYPE_MASK;
+     return buf;
  }
  
 +/* For an MD2 NSH header returns a pointer to an ofpbuf with the encoded
 + * MD2 TLVs provided as encap properties to the encap operation. This
 + * will be stored as encap_data in the ctx and copied into the encap_nsh
 + * action at the next commit. */
 +static struct ofpbuf *
 +rewrite_flow_encap_nsh(struct xlate_ctx *ctx,
 +                       const struct ofpact_encap *encap,
 +                       struct flow *flow,
 +                       struct flow_wildcards *wc)
 +{
 +    ovs_be32 packet_type = flow->packet_type;
 +    const char *ptr = (char *) encap->props;
 +    struct ofpbuf *buf = ofpbuf_new(OVS_ENCAP_NSH_MAX_MD_LEN);
 +    uint8_t md_type = NSH_M_TYPE1;
 +    uint8_t np = 0;
 +    int i;
 +
 +    /* Scan the optional NSH encap TLV properties, if any. */
 +    for (i = 0; i < encap->n_props; i++) {
 +        struct ofpact_ed_prop *prop_ptr =
 +            ALIGNED_CAST(struct ofpact_ed_prop *, ptr);
 +        if (prop_ptr->prop_class == OFPPPC_NSH) {
 +            switch (prop_ptr->type) {
 +                case OFPPPT_PROP_NSH_MDTYPE: {
 +                    struct ofpact_ed_prop_nsh_md_type *prop_md_type =
 +                        ALIGNED_CAST(struct ofpact_ed_prop_nsh_md_type *,
 +                                     prop_ptr);
 +                    md_type = prop_md_type->md_type;
 +                    break;
 +                }
 +                case OFPPPT_PROP_NSH_TLV: {
 +                    struct ofpact_ed_prop_nsh_tlv *tlv_prop =
 +                        ALIGNED_CAST(struct ofpact_ed_prop_nsh_tlv *,
 +                                     prop_ptr);
 +                    struct nsh_md2_tlv *md2_ctx =
 +                            ofpbuf_put_uninit(buf, sizeof(*md2_ctx));
 +                    md2_ctx->md_class = tlv_prop->tlv_class;
 +                    md2_ctx->type = tlv_prop->tlv_type;
 +                    md2_ctx->length = tlv_prop->tlv_len;
 +                    size_t len = ROUND_UP(md2_ctx->length, 4);
 +                    size_t padding = len - md2_ctx->length;
 +                    ofpbuf_put(buf, tlv_prop->data, md2_ctx->length);
 +                    ofpbuf_put_zeros(buf, padding);
 +                    break;
 +                }
 +                default:
 +                    /* No other NSH encap properties defined yet. */
 +                    break;
 +            }
 +        }
 +        ptr += ROUND_UP(prop_ptr->len, 8);
 +    }
 +    if (buf->size == 0 || buf->size > OVS_ENCAP_NSH_MAX_MD_LEN) {
 +        ofpbuf_delete(buf);
 +        buf = NULL;
 +    }
 +
 +    /* Determine the Next Protocol field for NSH header. */
 +    switch (ntohl(packet_type)) {
 +        case PT_ETH:
 +            np = NSH_P_ETHERNET;
 +            break;
 +        case PT_IPV4:
 +            np = NSH_P_IPV4;
 +            break;
 +        case PT_IPV6:
 +            np = NSH_P_IPV6;
 +            break;
 +        case PT_NSH:
 +            np = NSH_P_NSH;
 +            break;
 +        default:
 +            /* Error handling: drop packet. */
 +            xlate_report_debug(ctx, OFT_ACTION,
 +                               "Dropping packet as encap(nsh) is not "
 +                               "supported for packet type (%d,0x%x)",
 +                               pt_ns(packet_type), pt_ns_type(packet_type));
 +            ctx->error = 1;
 +            return buf;
 +    }
 +    /* Note that we have matched on packet_type! */
 +    wc->masks.packet_type = OVS_BE32_MAX;
 +
 +    /* Reset all current flow packet headers. */
 +    memset(&flow->dl_dst, 0,
 +           sizeof(struct flow) - offsetof(struct flow, dl_dst));
 +
 +    /* Populate the flow with the new NSH header. */
 +    flow->packet_type = htonl(PT_NSH);
 +    flow->dl_type = htons(ETH_TYPE_NSH);
 +    flow->nsh.flags = 0;    /* */
 +    flow->nsh.np = np;
 +    flow->nsh.spi = 0;
 +    flow->nsh.si = 255;
 +
 +    if (md_type == NSH_M_TYPE1) {
 +        flow->nsh.mdtype = NSH_M_TYPE1;
 +        memset(flow->nsh.c, 0, sizeof flow->nsh.c);
 +        if (buf) {
 +            /* Drop any MD2 context TLVs. */
 +            ofpbuf_delete(buf);
 +            buf = NULL;
 +        }
 +    } else if (md_type == NSH_M_TYPE2) {
 +        flow->nsh.mdtype = NSH_M_TYPE2;
 +    }
 +
 +    return buf;
 +}
 +
  static void
  xlate_generic_encap_action(struct xlate_ctx *ctx,
                             const struct ofpact_encap *encap)