linux/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h
<<
>>
Prefs
   1/*
   2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
   3 *
   4 * Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
   5 *
   6 * This software is available to you under a choice of one of two
   7 * licenses.  You may choose to be licensed under the terms of the GNU
   8 * General Public License (GPL) Version 2, available from the file
   9 * COPYING in the main directory of this source tree, or the
  10 * OpenIB.org BSD license below:
  11 *
  12 *     Redistribution and use in source and binary forms, with or
  13 *     without modification, are permitted provided that the following
  14 *     conditions are met:
  15 *
  16 *      - Redistributions of source code must retain the above
  17 *        copyright notice, this list of conditions and the following
  18 *        disclaimer.
  19 *
  20 *      - Redistributions in binary form must reproduce the above
  21 *        copyright notice, this list of conditions and the following
  22 *        disclaimer in the documentation and/or other materials
  23 *        provided with the distribution.
  24 *
  25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  32 * SOFTWARE.
  33 */
  34
  35#ifndef __CXGB4_TC_U32_PARSE_H
  36#define __CXGB4_TC_U32_PARSE_H
  37
  38struct cxgb4_match_field {
  39        int off; /* Offset from the beginning of the header to match */
  40        /* Fill the value/mask pair in the spec if matched */
  41        int (*val)(struct ch_filter_specification *f, __be32 val, __be32 mask);
  42};
  43
  44/* IPv4 match fields */
  45static inline int cxgb4_fill_ipv4_tos(struct ch_filter_specification *f,
  46                                      __be32 val, __be32 mask)
  47{
  48        f->val.tos  = (ntohl(val)  >> 16) & 0x000000FF;
  49        f->mask.tos = (ntohl(mask) >> 16) & 0x000000FF;
  50
  51        return 0;
  52}
  53
  54static inline int cxgb4_fill_ipv4_frag(struct ch_filter_specification *f,
  55                                       __be32 val, __be32 mask)
  56{
  57        u32 mask_val;
  58        u8 frag_val;
  59
  60        frag_val = (ntohl(val) >> 13) & 0x00000007;
  61        mask_val = ntohl(mask) & 0x0000FFFF;
  62
  63        if (frag_val == 0x1 && mask_val != 0x3FFF) { /* MF set */
  64                f->val.frag = 1;
  65                f->mask.frag = 1;
  66        } else if (frag_val == 0x2 && mask_val != 0x3FFF) { /* DF set */
  67                f->val.frag = 0;
  68                f->mask.frag = 1;
  69        } else {
  70                return -EINVAL;
  71        }
  72
  73        return 0;
  74}
  75
  76static inline int cxgb4_fill_ipv4_proto(struct ch_filter_specification *f,
  77                                        __be32 val, __be32 mask)
  78{
  79        f->val.proto  = (ntohl(val)  >> 16) & 0x000000FF;
  80        f->mask.proto = (ntohl(mask) >> 16) & 0x000000FF;
  81
  82        return 0;
  83}
  84
  85static inline int cxgb4_fill_ipv4_src_ip(struct ch_filter_specification *f,
  86                                         __be32 val, __be32 mask)
  87{
  88        memcpy(&f->val.fip[0],  &val,  sizeof(u32));
  89        memcpy(&f->mask.fip[0], &mask, sizeof(u32));
  90
  91        return 0;
  92}
  93
  94static inline int cxgb4_fill_ipv4_dst_ip(struct ch_filter_specification *f,
  95                                         __be32 val, __be32 mask)
  96{
  97        memcpy(&f->val.lip[0],  &val,  sizeof(u32));
  98        memcpy(&f->mask.lip[0], &mask, sizeof(u32));
  99
 100        return 0;
 101}
 102
 103static const struct cxgb4_match_field cxgb4_ipv4_fields[] = {
 104        { .off = 0,  .val = cxgb4_fill_ipv4_tos },
 105        { .off = 4,  .val = cxgb4_fill_ipv4_frag },
 106        { .off = 8,  .val = cxgb4_fill_ipv4_proto },
 107        { .off = 12, .val = cxgb4_fill_ipv4_src_ip },
 108        { .off = 16, .val = cxgb4_fill_ipv4_dst_ip },
 109        { .val = NULL }
 110};
 111
 112/* IPv6 match fields */
 113static inline int cxgb4_fill_ipv6_tos(struct ch_filter_specification *f,
 114                                      __be32 val, __be32 mask)
 115{
 116        f->val.tos  = (ntohl(val)  >> 20) & 0x000000FF;
 117        f->mask.tos = (ntohl(mask) >> 20) & 0x000000FF;
 118
 119        return 0;
 120}
 121
 122static inline int cxgb4_fill_ipv6_proto(struct ch_filter_specification *f,
 123                                        __be32 val, __be32 mask)
 124{
 125        f->val.proto  = (ntohl(val)  >> 8) & 0x000000FF;
 126        f->mask.proto = (ntohl(mask) >> 8) & 0x000000FF;
 127
 128        return 0;
 129}
 130
 131static inline int cxgb4_fill_ipv6_src_ip0(struct ch_filter_specification *f,
 132                                          __be32 val, __be32 mask)
 133{
 134        memcpy(&f->val.fip[0],  &val,  sizeof(u32));
 135        memcpy(&f->mask.fip[0], &mask, sizeof(u32));
 136
 137        return 0;
 138}
 139
 140static inline int cxgb4_fill_ipv6_src_ip1(struct ch_filter_specification *f,
 141                                          __be32 val, __be32 mask)
 142{
 143        memcpy(&f->val.fip[4],  &val,  sizeof(u32));
 144        memcpy(&f->mask.fip[4], &mask, sizeof(u32));
 145
 146        return 0;
 147}
 148
 149static inline int cxgb4_fill_ipv6_src_ip2(struct ch_filter_specification *f,
 150                                          __be32 val, __be32 mask)
 151{
 152        memcpy(&f->val.fip[8],  &val,  sizeof(u32));
 153        memcpy(&f->mask.fip[8], &mask, sizeof(u32));
 154
 155        return 0;
 156}
 157
 158static inline int cxgb4_fill_ipv6_src_ip3(struct ch_filter_specification *f,
 159                                          __be32 val, __be32 mask)
 160{
 161        memcpy(&f->val.fip[12],  &val,  sizeof(u32));
 162        memcpy(&f->mask.fip[12], &mask, sizeof(u32));
 163
 164        return 0;
 165}
 166
 167static inline int cxgb4_fill_ipv6_dst_ip0(struct ch_filter_specification *f,
 168                                          __be32 val, __be32 mask)
 169{
 170        memcpy(&f->val.lip[0],  &val,  sizeof(u32));
 171        memcpy(&f->mask.lip[0], &mask, sizeof(u32));
 172
 173        return 0;
 174}
 175
 176static inline int cxgb4_fill_ipv6_dst_ip1(struct ch_filter_specification *f,
 177                                          __be32 val, __be32 mask)
 178{
 179        memcpy(&f->val.lip[4],  &val,  sizeof(u32));
 180        memcpy(&f->mask.lip[4], &mask, sizeof(u32));
 181
 182        return 0;
 183}
 184
 185static inline int cxgb4_fill_ipv6_dst_ip2(struct ch_filter_specification *f,
 186                                          __be32 val, __be32 mask)
 187{
 188        memcpy(&f->val.lip[8],  &val,  sizeof(u32));
 189        memcpy(&f->mask.lip[8], &mask, sizeof(u32));
 190
 191        return 0;
 192}
 193
 194static inline int cxgb4_fill_ipv6_dst_ip3(struct ch_filter_specification *f,
 195                                          __be32 val, __be32 mask)
 196{
 197        memcpy(&f->val.lip[12],  &val,  sizeof(u32));
 198        memcpy(&f->mask.lip[12], &mask, sizeof(u32));
 199
 200        return 0;
 201}
 202
 203static const struct cxgb4_match_field cxgb4_ipv6_fields[] = {
 204        { .off = 0,  .val = cxgb4_fill_ipv6_tos },
 205        { .off = 4,  .val = cxgb4_fill_ipv6_proto },
 206        { .off = 8,  .val = cxgb4_fill_ipv6_src_ip0 },
 207        { .off = 12, .val = cxgb4_fill_ipv6_src_ip1 },
 208        { .off = 16, .val = cxgb4_fill_ipv6_src_ip2 },
 209        { .off = 20, .val = cxgb4_fill_ipv6_src_ip3 },
 210        { .off = 24, .val = cxgb4_fill_ipv6_dst_ip0 },
 211        { .off = 28, .val = cxgb4_fill_ipv6_dst_ip1 },
 212        { .off = 32, .val = cxgb4_fill_ipv6_dst_ip2 },
 213        { .off = 36, .val = cxgb4_fill_ipv6_dst_ip3 },
 214        { .val = NULL }
 215};
 216
 217/* TCP/UDP match */
 218static inline int cxgb4_fill_l4_ports(struct ch_filter_specification *f,
 219                                      __be32 val, __be32 mask)
 220{
 221        f->val.fport  = ntohl(val)  >> 16;
 222        f->mask.fport = ntohl(mask) >> 16;
 223        f->val.lport  = ntohl(val)  & 0x0000FFFF;
 224        f->mask.lport = ntohl(mask) & 0x0000FFFF;
 225
 226        return 0;
 227};
 228
 229static const struct cxgb4_match_field cxgb4_tcp_fields[] = {
 230        { .off = 0, .val = cxgb4_fill_l4_ports },
 231        { .val = NULL }
 232};
 233
 234static const struct cxgb4_match_field cxgb4_udp_fields[] = {
 235        { .off = 0, .val = cxgb4_fill_l4_ports },
 236        { .val = NULL }
 237};
 238
 239struct cxgb4_next_header {
 240        /* Offset, shift, and mask added to beginning of the header
 241         * to get to next header.  Useful when using a header
 242         * field's value to jump to next header such as IHL field
 243         * in IPv4 header.
 244         */
 245        struct tc_u32_sel sel;
 246        struct tc_u32_key key;
 247        /* location of jump to make */
 248        const struct cxgb4_match_field *jump;
 249};
 250
 251/* Accept a rule with a jump to transport layer header based on IHL field in
 252 * IPv4 header.
 253 */
 254static const struct cxgb4_next_header cxgb4_ipv4_jumps[] = {
 255        {
 256                /* TCP Jump */
 257                .sel = {
 258                        .off = 0,
 259                        .offoff = 0,
 260                        .offshift = 6,
 261                        .offmask = cpu_to_be16(0x0f00),
 262                },
 263                .key = {
 264                        .off = 8,
 265                        .val = cpu_to_be32(0x00060000),
 266                        .mask = cpu_to_be32(0x00ff0000),
 267                },
 268                .jump = cxgb4_tcp_fields,
 269        },
 270        {
 271                /* UDP Jump */
 272                .sel = {
 273                        .off = 0,
 274                        .offoff = 0,
 275                        .offshift = 6,
 276                        .offmask = cpu_to_be16(0x0f00),
 277                },
 278                .key = {
 279                        .off = 8,
 280                        .val = cpu_to_be32(0x00110000),
 281                        .mask = cpu_to_be32(0x00ff0000),
 282                },
 283                .jump = cxgb4_udp_fields,
 284        },
 285        { .jump = NULL },
 286};
 287
 288/* Accept a rule with a jump directly past the 40 Bytes of IPv6 fixed header
 289 * to get to transport layer header.
 290 */
 291static const struct cxgb4_next_header cxgb4_ipv6_jumps[] = {
 292        {
 293                /* TCP Jump */
 294                .sel = {
 295                        .off = 40,
 296                        .offoff = 0,
 297                        .offshift = 0,
 298                        .offmask = 0,
 299                },
 300                .key = {
 301                        .off = 4,
 302                        .val = cpu_to_be32(0x00000600),
 303                        .mask = cpu_to_be32(0x0000ff00),
 304                },
 305                .jump = cxgb4_tcp_fields,
 306        },
 307        {
 308                /* UDP Jump */
 309                .sel = {
 310                        .off = 40,
 311                        .offoff = 0,
 312                        .offshift = 0,
 313                        .offmask = 0,
 314                },
 315                .key = {
 316                        .off = 4,
 317                        .val = cpu_to_be32(0x00001100),
 318                        .mask = cpu_to_be32(0x0000ff00),
 319                },
 320                .jump = cxgb4_udp_fields,
 321        },
 322        { .jump = NULL },
 323};
 324
 325struct cxgb4_link {
 326        const struct cxgb4_match_field *match_field;  /* Next header */
 327        struct ch_filter_specification fs; /* Match spec associated with link */
 328        u32 link_handle;         /* Knode handle associated with the link */
 329        unsigned long *tid_map;  /* Bitmap for filter tids */
 330};
 331
 332struct cxgb4_tc_u32_table {
 333        unsigned int size;          /* number of entries in table */
 334        struct cxgb4_link table[]; /* Jump table */
 335};
 336#endif /* __CXGB4_TC_U32_PARSE_H */
 337