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, u32 val, u32 mask);
  42};
  43
  44/* IPv4 match fields */
  45static inline int cxgb4_fill_ipv4_tos(struct ch_filter_specification *f,
  46                                      u32 val, u32 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                                       u32 val, u32 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                                        u32 val, u32 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                                         u32 val, u32 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                                         u32 val, u32 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                                      u32 val, u32 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                                        u32 val, u32 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                                          u32 val, u32 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                                          u32 val, u32 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                                          u32 val, u32 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                                          u32 val, u32 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                                          u32 val, u32 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                                          u32 val, u32 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                                          u32 val, u32 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                                          u32 val, u32 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                                      u32 val, u32 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        unsigned int offset; /* Offset to next header */
 241        /* offset, shift, and mask added to offset above
 242         * to get to next header.  Useful when using a header
 243         * field's value to jump to next header such as IHL field
 244         * in IPv4 header.
 245         */
 246        unsigned int offoff;
 247        u32 shift;
 248        u32 mask;
 249        /* match criteria to make this jump */
 250        unsigned int match_off;
 251        u32 match_val;
 252        u32 match_mask;
 253        /* location of jump to make */
 254        const struct cxgb4_match_field *jump;
 255};
 256
 257/* Accept a rule with a jump to transport layer header based on IHL field in
 258 * IPv4 header.
 259 */
 260static const struct cxgb4_next_header cxgb4_ipv4_jumps[] = {
 261        { .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
 262          .match_off = 8, .match_val = 0x600, .match_mask = 0xFF00,
 263          .jump = cxgb4_tcp_fields },
 264        { .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
 265          .match_off = 8, .match_val = 0x1100, .match_mask = 0xFF00,
 266          .jump = cxgb4_udp_fields },
 267        { .jump = NULL }
 268};
 269
 270/* Accept a rule with a jump directly past the 40 Bytes of IPv6 fixed header
 271 * to get to transport layer header.
 272 */
 273static const struct cxgb4_next_header cxgb4_ipv6_jumps[] = {
 274        { .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
 275          .match_off = 4, .match_val = 0x60000, .match_mask = 0xFF0000,
 276          .jump = cxgb4_tcp_fields },
 277        { .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
 278          .match_off = 4, .match_val = 0x110000, .match_mask = 0xFF0000,
 279          .jump = cxgb4_udp_fields },
 280        { .jump = NULL }
 281};
 282
 283struct cxgb4_link {
 284        const struct cxgb4_match_field *match_field;  /* Next header */
 285        struct ch_filter_specification fs; /* Match spec associated with link */
 286        u32 link_handle;         /* Knode handle associated with the link */
 287        unsigned long *tid_map;  /* Bitmap for filter tids */
 288};
 289
 290struct cxgb4_tc_u32_table {
 291        unsigned int size;          /* number of entries in table */
 292        struct cxgb4_link table[0]; /* Jump table */
 293};
 294#endif /* __CXGB4_TC_U32_PARSE_H */
 295