parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key)
{
    const struct nsh_hdr *nsh = (const struct nsh_hdr *) *datap;
    uint16_t ver_flags_len;
    uint8_t version, length, flags;
    uint32_t path_hdr;

    /* Check if it is long enough for NSH header, doesn't support
     * MD type 2 yet
     */
    if (OVS_UNLIKELY(*sizep < NSH_BASE_HDR_LEN)) {
        return false;
    }

    memset(key, 0, sizeof(struct flow_nsh));

    ver_flags_len = ntohs(nsh->ver_flags_ttl_len);
    version = (ver_flags_len & NSH_VER_MASK) >> NSH_VER_SHIFT;
    flags = (ver_flags_len & NSH_FLAGS_MASK) >> NSH_FLAGS_SHIFT;

    /* NSH header length is in 4 byte words. */
    length = ((ver_flags_len & NSH_LEN_MASK) >> NSH_LEN_SHIFT) << 2;

    if (length > *sizep || version != 0) {
        return false;
    }

    key->flags = flags;
    key->mdtype = nsh->md_type;
    key->np = nsh->next_proto;

    path_hdr = ntohl(get_16aligned_be32(&nsh->path_hdr));
    key->si = (path_hdr & NSH_SI_MASK) >> NSH_SI_SHIFT;
    key->spi = htonl((path_hdr & NSH_SPI_MASK) >> NSH_SPI_SHIFT);

    switch (key->mdtype) {
        case NSH_M_TYPE1:
            if (length != NSH_M_TYPE1_LEN) {
                return false;
            }
            for (size_t i = 0; i < 4; i++) {
                key->c[i] = get_16aligned_be32(&nsh->md1.c[i]);
            }
            break;
        case NSH_M_TYPE2:
        default:
            /* We don't parse other context headers yet. */
            break;
    }

    data_pull(datap, sizep, length);

    return true;
}
parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key)
{
    const struct nsh_hdr *nsh = (const struct nsh_hdr *) *datap;
    uint16_t ver_flags_len;
    uint8_t version, length, flags;
    uint32_t path_hdr;

     
    if (OVS_UNLIKELY(*sizep < NSH_BASE_HDR_LEN)) {
        return false;
    }

    memset(key, 0, sizeof(struct flow_nsh));

    ver_flags_len = ntohs(nsh->ver_flags_ttl_len);
    version = (ver_flags_len & NSH_VER_MASK) >> NSH_VER_SHIFT;
    flags = (ver_flags_len & NSH_FLAGS_MASK) >> NSH_FLAGS_SHIFT;

     
    length = ((ver_flags_len & NSH_LEN_MASK) >> NSH_LEN_SHIFT) << 2;

    if (length > *sizep || version != 0) {
        return false;
    }

    key->flags = flags;
    key->mdtype = nsh->md_type;
    key->np = nsh->next_proto;

    path_hdr = ntohl(get_16aligned_be32(&nsh->path_hdr));
    key->si = (path_hdr & NSH_SI_MASK) >> NSH_SI_SHIFT;
    key->spi = htonl((path_hdr & NSH_SPI_MASK) >> NSH_SPI_SHIFT);

    switch (key->mdtype) {
        case NSH_M_TYPE1:
            if (length != NSH_M_TYPE1_LEN) {
                return false;
            }
            for (size_t i = 0; i < 4; i++) {
                key->c[i] = get_16aligned_be32(&nsh->md1.c[i]);
            }
            break;
        case NSH_M_TYPE2:
        default:
             
            break;
    }

    data_pull(datap, sizep, length);

    return true;
}