root/drivers/net/xen-netback/hash.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xenvif_add_hash
  2. xenvif_new_hash
  3. xenvif_flush_hash
  4. xenvif_find_hash
  5. xenvif_set_skb_hash
  6. xenvif_set_hash_alg
  7. xenvif_get_hash_flags
  8. xenvif_set_hash_flags
  9. xenvif_set_hash_key
  10. xenvif_set_hash_mapping_size
  11. xenvif_set_hash_mapping
  12. xenvif_dump_hash_info
  13. xenvif_init_hash
  14. xenvif_deinit_hash

   1 /*
   2  * Copyright (c) 2016 Citrix Systems Inc.
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public License version 2
   6  * as published by the Free Softare Foundation; or, when distributed
   7  * separately from the Linux kernel or incorporated into other
   8  * software packages, subject to the following license:
   9  *
  10  * Permission is hereby granted, free of charge, to any person obtaining a copy
  11  * of this source file (the "Software"), to deal in the Software without
  12  * restriction, including without limitation the rights to use, copy, modify,
  13  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
  14  * and to permit persons to whom the Software is furnished to do so, subject to
  15  * the following conditions:
  16  *
  17  * The above copyright notice and this permission notice shall be included in
  18  * all copies or substantial portions of the Software.
  19  *
  20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  26  * IN THE SOFTWARE.
  27  */
  28 
  29 #define XEN_NETIF_DEFINE_TOEPLITZ
  30 
  31 #include "common.h"
  32 #include <linux/vmalloc.h>
  33 #include <linux/rculist.h>
  34 
  35 static void xenvif_add_hash(struct xenvif *vif, const u8 *tag,
  36                             unsigned int len, u32 val)
  37 {
  38         struct xenvif_hash_cache_entry *new, *entry, *oldest;
  39         unsigned long flags;
  40         bool found;
  41 
  42         new = kmalloc(sizeof(*entry), GFP_ATOMIC);
  43         if (!new)
  44                 return;
  45 
  46         memcpy(new->tag, tag, len);
  47         new->len = len;
  48         new->val = val;
  49 
  50         spin_lock_irqsave(&vif->hash.cache.lock, flags);
  51 
  52         found = false;
  53         oldest = NULL;
  54         list_for_each_entry_rcu(entry, &vif->hash.cache.list, link) {
  55                 /* Make sure we don't add duplicate entries */
  56                 if (entry->len == len &&
  57                     memcmp(entry->tag, tag, len) == 0)
  58                         found = true;
  59                 if (!oldest || entry->seq < oldest->seq)
  60                         oldest = entry;
  61         }
  62 
  63         if (!found) {
  64                 new->seq = atomic_inc_return(&vif->hash.cache.seq);
  65                 list_add_rcu(&new->link, &vif->hash.cache.list);
  66 
  67                 if (++vif->hash.cache.count > xenvif_hash_cache_size) {
  68                         list_del_rcu(&oldest->link);
  69                         vif->hash.cache.count--;
  70                         kfree_rcu(oldest, rcu);
  71                 }
  72         }
  73 
  74         spin_unlock_irqrestore(&vif->hash.cache.lock, flags);
  75 
  76         if (found)
  77                 kfree(new);
  78 }
  79 
  80 static u32 xenvif_new_hash(struct xenvif *vif, const u8 *data,
  81                            unsigned int len)
  82 {
  83         u32 val;
  84 
  85         val = xen_netif_toeplitz_hash(vif->hash.key,
  86                                       sizeof(vif->hash.key),
  87                                       data, len);
  88 
  89         if (xenvif_hash_cache_size != 0)
  90                 xenvif_add_hash(vif, data, len, val);
  91 
  92         return val;
  93 }
  94 
  95 static void xenvif_flush_hash(struct xenvif *vif)
  96 {
  97         struct xenvif_hash_cache_entry *entry;
  98         unsigned long flags;
  99 
 100         if (xenvif_hash_cache_size == 0)
 101                 return;
 102 
 103         spin_lock_irqsave(&vif->hash.cache.lock, flags);
 104 
 105         list_for_each_entry_rcu(entry, &vif->hash.cache.list, link) {
 106                 list_del_rcu(&entry->link);
 107                 vif->hash.cache.count--;
 108                 kfree_rcu(entry, rcu);
 109         }
 110 
 111         spin_unlock_irqrestore(&vif->hash.cache.lock, flags);
 112 }
 113 
 114 static u32 xenvif_find_hash(struct xenvif *vif, const u8 *data,
 115                             unsigned int len)
 116 {
 117         struct xenvif_hash_cache_entry *entry;
 118         u32 val;
 119         bool found;
 120 
 121         if (len >= XEN_NETBK_HASH_TAG_SIZE)
 122                 return 0;
 123 
 124         if (xenvif_hash_cache_size == 0)
 125                 return xenvif_new_hash(vif, data, len);
 126 
 127         rcu_read_lock();
 128 
 129         found = false;
 130 
 131         list_for_each_entry_rcu(entry, &vif->hash.cache.list, link) {
 132                 if (entry->len == len &&
 133                     memcmp(entry->tag, data, len) == 0) {
 134                         val = entry->val;
 135                         entry->seq = atomic_inc_return(&vif->hash.cache.seq);
 136                         found = true;
 137                         break;
 138                 }
 139         }
 140 
 141         rcu_read_unlock();
 142 
 143         if (!found)
 144                 val = xenvif_new_hash(vif, data, len);
 145 
 146         return val;
 147 }
 148 
 149 void xenvif_set_skb_hash(struct xenvif *vif, struct sk_buff *skb)
 150 {
 151         struct flow_keys flow;
 152         u32 hash = 0;
 153         enum pkt_hash_types type = PKT_HASH_TYPE_NONE;
 154         u32 flags = vif->hash.flags;
 155         bool has_tcp_hdr;
 156 
 157         /* Quick rejection test: If the network protocol doesn't
 158          * correspond to any enabled hash type then there's no point
 159          * in parsing the packet header.
 160          */
 161         switch (skb->protocol) {
 162         case htons(ETH_P_IP):
 163                 if (flags & (XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP |
 164                              XEN_NETIF_CTRL_HASH_TYPE_IPV4))
 165                         break;
 166 
 167                 goto done;
 168 
 169         case htons(ETH_P_IPV6):
 170                 if (flags & (XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP |
 171                              XEN_NETIF_CTRL_HASH_TYPE_IPV6))
 172                         break;
 173 
 174                 goto done;
 175 
 176         default:
 177                 goto done;
 178         }
 179 
 180         memset(&flow, 0, sizeof(flow));
 181         if (!skb_flow_dissect_flow_keys(skb, &flow, 0))
 182                 goto done;
 183 
 184         has_tcp_hdr = (flow.basic.ip_proto == IPPROTO_TCP) &&
 185                       !(flow.control.flags & FLOW_DIS_IS_FRAGMENT);
 186 
 187         switch (skb->protocol) {
 188         case htons(ETH_P_IP):
 189                 if (has_tcp_hdr &&
 190                     (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP)) {
 191                         u8 data[12];
 192 
 193                         memcpy(&data[0], &flow.addrs.v4addrs.src, 4);
 194                         memcpy(&data[4], &flow.addrs.v4addrs.dst, 4);
 195                         memcpy(&data[8], &flow.ports.src, 2);
 196                         memcpy(&data[10], &flow.ports.dst, 2);
 197 
 198                         hash = xenvif_find_hash(vif, data, sizeof(data));
 199                         type = PKT_HASH_TYPE_L4;
 200                 } else if (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4) {
 201                         u8 data[8];
 202 
 203                         memcpy(&data[0], &flow.addrs.v4addrs.src, 4);
 204                         memcpy(&data[4], &flow.addrs.v4addrs.dst, 4);
 205 
 206                         hash = xenvif_find_hash(vif, data, sizeof(data));
 207                         type = PKT_HASH_TYPE_L3;
 208                 }
 209 
 210                 break;
 211 
 212         case htons(ETH_P_IPV6):
 213                 if (has_tcp_hdr &&
 214                     (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP)) {
 215                         u8 data[36];
 216 
 217                         memcpy(&data[0], &flow.addrs.v6addrs.src, 16);
 218                         memcpy(&data[16], &flow.addrs.v6addrs.dst, 16);
 219                         memcpy(&data[32], &flow.ports.src, 2);
 220                         memcpy(&data[34], &flow.ports.dst, 2);
 221 
 222                         hash = xenvif_find_hash(vif, data, sizeof(data));
 223                         type = PKT_HASH_TYPE_L4;
 224                 } else if (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6) {
 225                         u8 data[32];
 226 
 227                         memcpy(&data[0], &flow.addrs.v6addrs.src, 16);
 228                         memcpy(&data[16], &flow.addrs.v6addrs.dst, 16);
 229 
 230                         hash = xenvif_find_hash(vif, data, sizeof(data));
 231                         type = PKT_HASH_TYPE_L3;
 232                 }
 233 
 234                 break;
 235         }
 236 
 237 done:
 238         if (type == PKT_HASH_TYPE_NONE)
 239                 skb_clear_hash(skb);
 240         else
 241                 __skb_set_sw_hash(skb, hash, type == PKT_HASH_TYPE_L4);
 242 }
 243 
 244 u32 xenvif_set_hash_alg(struct xenvif *vif, u32 alg)
 245 {
 246         switch (alg) {
 247         case XEN_NETIF_CTRL_HASH_ALGORITHM_NONE:
 248         case XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ:
 249                 break;
 250 
 251         default:
 252                 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 253         }
 254 
 255         vif->hash.alg = alg;
 256 
 257         return XEN_NETIF_CTRL_STATUS_SUCCESS;
 258 }
 259 
 260 u32 xenvif_get_hash_flags(struct xenvif *vif, u32 *flags)
 261 {
 262         if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
 263                 return XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED;
 264 
 265         *flags = XEN_NETIF_CTRL_HASH_TYPE_IPV4 |
 266                  XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP |
 267                  XEN_NETIF_CTRL_HASH_TYPE_IPV6 |
 268                  XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP;
 269 
 270         return XEN_NETIF_CTRL_STATUS_SUCCESS;
 271 }
 272 
 273 u32 xenvif_set_hash_flags(struct xenvif *vif, u32 flags)
 274 {
 275         if (flags & ~(XEN_NETIF_CTRL_HASH_TYPE_IPV4 |
 276                       XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP |
 277                       XEN_NETIF_CTRL_HASH_TYPE_IPV6 |
 278                       XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP))
 279                 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 280 
 281         if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
 282                 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 283 
 284         vif->hash.flags = flags;
 285 
 286         return XEN_NETIF_CTRL_STATUS_SUCCESS;
 287 }
 288 
 289 u32 xenvif_set_hash_key(struct xenvif *vif, u32 gref, u32 len)
 290 {
 291         u8 *key = vif->hash.key;
 292         struct gnttab_copy copy_op = {
 293                 .source.u.ref = gref,
 294                 .source.domid = vif->domid,
 295                 .dest.u.gmfn = virt_to_gfn(key),
 296                 .dest.domid = DOMID_SELF,
 297                 .dest.offset = xen_offset_in_page(key),
 298                 .len = len,
 299                 .flags = GNTCOPY_source_gref
 300         };
 301 
 302         if (len > XEN_NETBK_MAX_HASH_KEY_SIZE)
 303                 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 304 
 305         if (copy_op.len != 0) {
 306                 gnttab_batch_copy(&copy_op, 1);
 307 
 308                 if (copy_op.status != GNTST_okay)
 309                         return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 310         }
 311 
 312         /* Clear any remaining key octets */
 313         if (len < XEN_NETBK_MAX_HASH_KEY_SIZE)
 314                 memset(key + len, 0, XEN_NETBK_MAX_HASH_KEY_SIZE - len);
 315 
 316         xenvif_flush_hash(vif);
 317 
 318         return XEN_NETIF_CTRL_STATUS_SUCCESS;
 319 }
 320 
 321 u32 xenvif_set_hash_mapping_size(struct xenvif *vif, u32 size)
 322 {
 323         if (size > XEN_NETBK_MAX_HASH_MAPPING_SIZE)
 324                 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 325 
 326         vif->hash.size = size;
 327         memset(vif->hash.mapping[vif->hash.mapping_sel], 0,
 328                sizeof(u32) * size);
 329 
 330         return XEN_NETIF_CTRL_STATUS_SUCCESS;
 331 }
 332 
 333 u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len,
 334                             u32 off)
 335 {
 336         u32 *mapping = vif->hash.mapping[!vif->hash.mapping_sel];
 337         unsigned int nr = 1;
 338         struct gnttab_copy copy_op[2] = {{
 339                 .source.u.ref = gref,
 340                 .source.domid = vif->domid,
 341                 .dest.domid = DOMID_SELF,
 342                 .len = len * sizeof(*mapping),
 343                 .flags = GNTCOPY_source_gref
 344         }};
 345 
 346         if ((off + len < off) || (off + len > vif->hash.size) ||
 347             len > XEN_PAGE_SIZE / sizeof(*mapping))
 348                 return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 349 
 350         copy_op[0].dest.u.gmfn = virt_to_gfn(mapping + off);
 351         copy_op[0].dest.offset = xen_offset_in_page(mapping + off);
 352         if (copy_op[0].dest.offset + copy_op[0].len > XEN_PAGE_SIZE) {
 353                 copy_op[1] = copy_op[0];
 354                 copy_op[1].source.offset = XEN_PAGE_SIZE - copy_op[0].dest.offset;
 355                 copy_op[1].dest.u.gmfn = virt_to_gfn(mapping + off + len);
 356                 copy_op[1].dest.offset = 0;
 357                 copy_op[1].len = copy_op[0].len - copy_op[1].source.offset;
 358                 copy_op[0].len = copy_op[1].source.offset;
 359                 nr = 2;
 360         }
 361 
 362         memcpy(mapping, vif->hash.mapping[vif->hash.mapping_sel],
 363                vif->hash.size * sizeof(*mapping));
 364 
 365         if (copy_op[0].len != 0) {
 366                 gnttab_batch_copy(copy_op, nr);
 367 
 368                 if (copy_op[0].status != GNTST_okay ||
 369                     copy_op[nr - 1].status != GNTST_okay)
 370                         return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 371         }
 372 
 373         while (len-- != 0)
 374                 if (mapping[off++] >= vif->num_queues)
 375                         return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
 376 
 377         vif->hash.mapping_sel = !vif->hash.mapping_sel;
 378 
 379         return XEN_NETIF_CTRL_STATUS_SUCCESS;
 380 }
 381 
 382 #ifdef CONFIG_DEBUG_FS
 383 void xenvif_dump_hash_info(struct xenvif *vif, struct seq_file *m)
 384 {
 385         unsigned int i;
 386 
 387         switch (vif->hash.alg) {
 388         case XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ:
 389                 seq_puts(m, "Hash Algorithm: TOEPLITZ\n");
 390                 break;
 391 
 392         case XEN_NETIF_CTRL_HASH_ALGORITHM_NONE:
 393                 seq_puts(m, "Hash Algorithm: NONE\n");
 394                 /* FALLTHRU */
 395         default:
 396                 return;
 397         }
 398 
 399         if (vif->hash.flags) {
 400                 seq_puts(m, "\nHash Flags:\n");
 401 
 402                 if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4)
 403                         seq_puts(m, "- IPv4\n");
 404                 if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP)
 405                         seq_puts(m, "- IPv4 + TCP\n");
 406                 if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6)
 407                         seq_puts(m, "- IPv6\n");
 408                 if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP)
 409                         seq_puts(m, "- IPv6 + TCP\n");
 410         }
 411 
 412         seq_puts(m, "\nHash Key:\n");
 413 
 414         for (i = 0; i < XEN_NETBK_MAX_HASH_KEY_SIZE; ) {
 415                 unsigned int j, n;
 416 
 417                 n = 8;
 418                 if (i + n >= XEN_NETBK_MAX_HASH_KEY_SIZE)
 419                         n = XEN_NETBK_MAX_HASH_KEY_SIZE - i;
 420 
 421                 seq_printf(m, "[%2u - %2u]: ", i, i + n - 1);
 422 
 423                 for (j = 0; j < n; j++, i++)
 424                         seq_printf(m, "%02x ", vif->hash.key[i]);
 425 
 426                 seq_puts(m, "\n");
 427         }
 428 
 429         if (vif->hash.size != 0) {
 430                 const u32 *mapping = vif->hash.mapping[vif->hash.mapping_sel];
 431 
 432                 seq_puts(m, "\nHash Mapping:\n");
 433 
 434                 for (i = 0; i < vif->hash.size; ) {
 435                         unsigned int j, n;
 436 
 437                         n = 8;
 438                         if (i + n >= vif->hash.size)
 439                                 n = vif->hash.size - i;
 440 
 441                         seq_printf(m, "[%4u - %4u]: ", i, i + n - 1);
 442 
 443                         for (j = 0; j < n; j++, i++)
 444                                 seq_printf(m, "%4u ", mapping[i]);
 445 
 446                         seq_puts(m, "\n");
 447                 }
 448         }
 449 }
 450 #endif /* CONFIG_DEBUG_FS */
 451 
 452 void xenvif_init_hash(struct xenvif *vif)
 453 {
 454         if (xenvif_hash_cache_size == 0)
 455                 return;
 456 
 457         BUG_ON(vif->hash.cache.count);
 458 
 459         spin_lock_init(&vif->hash.cache.lock);
 460         INIT_LIST_HEAD(&vif->hash.cache.list);
 461 }
 462 
 463 void xenvif_deinit_hash(struct xenvif *vif)
 464 {
 465         xenvif_flush_hash(vif);
 466 }

/* [<][>][^][v][top][bottom][index][help] */