cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

transport.c (4576B)


      1/*
      2 * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
      3 *
      4 * This software is available to you under a choice of one of two
      5 * licenses.  You may choose to be licensed under the terms of the GNU
      6 * General Public License (GPL) Version 2, available from the file
      7 * COPYING in the main directory of this source tree, or the
      8 * OpenIB.org BSD license below:
      9 *
     10 *     Redistribution and use in source and binary forms, with or
     11 *     without modification, are permitted provided that the following
     12 *     conditions are met:
     13 *
     14 *      - Redistributions of source code must retain the above
     15 *        copyright notice, this list of conditions and the following
     16 *        disclaimer.
     17 *
     18 *      - Redistributions in binary form must reproduce the above
     19 *        copyright notice, this list of conditions and the following
     20 *        disclaimer in the documentation and/or other materials
     21 *        provided with the distribution.
     22 *
     23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     30 * SOFTWARE.
     31 *
     32 */
     33#include <linux/kernel.h>
     34#include <linux/module.h>
     35#include <linux/in.h>
     36#include <linux/ipv6.h>
     37
     38#include "rds.h"
     39#include "loop.h"
     40
     41static char * const rds_trans_modules[] = {
     42	[RDS_TRANS_IB] = "rds_rdma",
     43	[RDS_TRANS_GAP] = NULL,
     44	[RDS_TRANS_TCP] = "rds_tcp",
     45};
     46
     47static struct rds_transport *transports[RDS_TRANS_COUNT];
     48static DECLARE_RWSEM(rds_trans_sem);
     49
     50void rds_trans_register(struct rds_transport *trans)
     51{
     52	BUG_ON(strlen(trans->t_name) + 1 > TRANSNAMSIZ);
     53
     54	down_write(&rds_trans_sem);
     55
     56	if (transports[trans->t_type])
     57		printk(KERN_ERR "RDS Transport type %d already registered\n",
     58			trans->t_type);
     59	else {
     60		transports[trans->t_type] = trans;
     61		printk(KERN_INFO "Registered RDS/%s transport\n", trans->t_name);
     62	}
     63
     64	up_write(&rds_trans_sem);
     65}
     66EXPORT_SYMBOL_GPL(rds_trans_register);
     67
     68void rds_trans_unregister(struct rds_transport *trans)
     69{
     70	down_write(&rds_trans_sem);
     71
     72	transports[trans->t_type] = NULL;
     73	printk(KERN_INFO "Unregistered RDS/%s transport\n", trans->t_name);
     74
     75	up_write(&rds_trans_sem);
     76}
     77EXPORT_SYMBOL_GPL(rds_trans_unregister);
     78
     79void rds_trans_put(struct rds_transport *trans)
     80{
     81	if (trans)
     82		module_put(trans->t_owner);
     83}
     84
     85struct rds_transport *rds_trans_get_preferred(struct net *net,
     86					      const struct in6_addr *addr,
     87					      __u32 scope_id)
     88{
     89	struct rds_transport *ret = NULL;
     90	struct rds_transport *trans;
     91	unsigned int i;
     92
     93	if (ipv6_addr_v4mapped(addr)) {
     94		if (*(u_int8_t *)&addr->s6_addr32[3] == IN_LOOPBACKNET)
     95			return &rds_loop_transport;
     96	} else if (ipv6_addr_loopback(addr)) {
     97		return &rds_loop_transport;
     98	}
     99
    100	down_read(&rds_trans_sem);
    101	for (i = 0; i < RDS_TRANS_COUNT; i++) {
    102		trans = transports[i];
    103
    104		if (trans && (trans->laddr_check(net, addr, scope_id) == 0) &&
    105		    (!trans->t_owner || try_module_get(trans->t_owner))) {
    106			ret = trans;
    107			break;
    108		}
    109	}
    110	up_read(&rds_trans_sem);
    111
    112	return ret;
    113}
    114
    115struct rds_transport *rds_trans_get(int t_type)
    116{
    117	struct rds_transport *ret = NULL;
    118	struct rds_transport *trans;
    119
    120	down_read(&rds_trans_sem);
    121	trans = transports[t_type];
    122	if (!trans) {
    123		up_read(&rds_trans_sem);
    124		if (rds_trans_modules[t_type])
    125			request_module(rds_trans_modules[t_type]);
    126		down_read(&rds_trans_sem);
    127		trans = transports[t_type];
    128	}
    129	if (trans && trans->t_type == t_type &&
    130	    (!trans->t_owner || try_module_get(trans->t_owner)))
    131		ret = trans;
    132
    133	up_read(&rds_trans_sem);
    134
    135	return ret;
    136}
    137
    138/*
    139 * This returns the number of stats entries in the snapshot and only
    140 * copies them using the iter if there is enough space for them.  The
    141 * caller passes in the global stats so that we can size and copy while
    142 * holding the lock.
    143 */
    144unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
    145				       unsigned int avail)
    146
    147{
    148	struct rds_transport *trans;
    149	unsigned int total = 0;
    150	unsigned int part;
    151	int i;
    152
    153	rds_info_iter_unmap(iter);
    154	down_read(&rds_trans_sem);
    155
    156	for (i = 0; i < RDS_TRANS_COUNT; i++) {
    157		trans = transports[i];
    158		if (!trans || !trans->stats_info_copy)
    159			continue;
    160
    161		part = trans->stats_info_copy(iter, avail);
    162		avail -= min(avail, part);
    163		total += part;
    164	}
    165
    166	up_read(&rds_trans_sem);
    167
    168	return total;
    169}