router.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,077 行 · 第 1/3 页

C
1,077
字号
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Copyright (C) 2002 Cluster File Systems, Inc. * *   This file is part of Portals *   http://sourceforge.net/projects/sandiaportals/ * *   Portals is free software; you can redistribute it and/or *   modify it under the terms of version 2 of the GNU General Public *   License as published by the Free Software Foundation. * *   Portals is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with Portals; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#define DEBUG_SUBSYSTEM S_LNET#include <lnet/lib-lnet.h>#if defined(__KERNEL__) && defined(LNET_ROUTER)static char *forwarding = "";CFS_MODULE_PARM(forwarding, "s", charp, 0444,                "Explicitly enable/disable forwarding between networks");static int tiny_router_buffers = 1024;CFS_MODULE_PARM(tiny_router_buffers, "i", int, 0444,                "# of 0 payload messages to buffer in the router");static int small_router_buffers = 8192;CFS_MODULE_PARM(small_router_buffers, "i", int, 0444,                "# of small (1 page) messages to buffer in the router");static int large_router_buffers = 512;CFS_MODULE_PARM(large_router_buffers, "i", int, 0444,                "# of large messages to buffer in the router");static int auto_down = 1;CFS_MODULE_PARM(auto_down, "i", int, 0444,                "Automatically mark peers down on comms error");static int check_routers_before_use = 0;CFS_MODULE_PARM(check_routers_before_use, "i", int, 0444,                "Assume routers are down and ping them before use");static int dead_router_check_interval = 0;CFS_MODULE_PARM(dead_router_check_interval, "i", int, 0444,                "Seconds between dead router health checks (<= 0 to disable)");static int live_router_check_interval = 0;CFS_MODULE_PARM(live_router_check_interval, "i", int, 0444,                "Seconds between live router health checks (<= 0 to disable)");static int router_ping_timeout = 50;CFS_MODULE_PARM(router_ping_timeout, "i", int, 0444,                "Seconds to wait for the reply to a router health query");intlnet_peers_start_down(void){        return check_routers_before_use;}voidlnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, time_t when){        if (when < lp->lp_timestamp) {          /* out of date information */                CDEBUG(D_NET, "Out of date\n");                return;        }        lp->lp_timestamp = when;                /* update timestamp */        lp->lp_ping_deadline = 0;               /* disable ping timeout */        if (lp->lp_alive_count != 0 &&          /* got old news */            (!lp->lp_alive) == (!alive)) {      /* new date for old news */                CDEBUG(D_NET, "Old news\n");                return;        }        /* Flag that notification is outstanding */        lp->lp_alive_count++;        lp->lp_alive = !(!alive);               /* 1 bit! */        lp->lp_notify = 1;        lp->lp_notifylnd |= notifylnd;        CDEBUG(D_NET, "set %s %d\n", libcfs_nid2str(lp->lp_nid), alive);}voidlnet_do_notify (lnet_peer_t *lp) {        lnet_ni_t *ni = lp->lp_ni;        int        alive;        int        notifylnd;                LNET_LOCK();                        /* Notify only in 1 thread at any time to ensure ordered notification.         * NB individual events can be missed; the only guarantee is that you         * always get the most recent news */        if (lp->lp_notifying) {                LNET_UNLOCK();                return;        }        lp->lp_notifying = 1;                while (lp->lp_notify) {                alive     = lp->lp_alive;                notifylnd = lp->lp_notifylnd;                lp->lp_notifylnd = 0;                lp->lp_notify    = 0;                if (notifylnd && ni->ni_lnd->lnd_notify != NULL) {                        LNET_UNLOCK();                        /* A new notification could happen now; I'll handle it                         * when control returns to me */                        (ni->ni_lnd->lnd_notify)(ni, lp->lp_nid, alive);                        LNET_LOCK();                }        }        lp->lp_notifying = 0;        LNET_UNLOCK();}intlnet_notify (lnet_ni_t *ni, lnet_nid_t nid, int alive, time_t when){        lnet_peer_t         *lp = NULL;        time_t               now = cfs_time_current_sec();        LASSERT (!in_interrupt ());        CDEBUG (D_NET, "%s notifying %s: %s\n",                (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid),                libcfs_nid2str(nid),                alive ? "up" : "down");        if (ni != NULL &&            LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid)) {                CWARN ("Ignoring notification of %s %s by %s (different net)\n",                        libcfs_nid2str(nid), alive ? "birth" : "death",                        libcfs_nid2str(ni->ni_nid));                return -EINVAL;        }        /* can't do predictions... */        if (when > now) {                CWARN ("Ignoring prediction from %s of %s %s "                       "%ld seconds in the future\n",                       (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid),                       libcfs_nid2str(nid), alive ? "up" : "down",                       when - now);                return -EINVAL;        }        if (ni != NULL && !alive &&             /* LND telling me she's down */            !auto_down) {                       /* auto-down disabled */                CDEBUG(D_NET, "Auto-down disabled\n");                return 0;        }                LNET_LOCK();        lp = lnet_find_peer_locked(nid);        if (lp == NULL) {                /* nid not found */                LNET_UNLOCK();                CDEBUG(D_NET, "%s not found\n", libcfs_nid2str(nid));                return 0;        }        lnet_notify_locked(lp, ni == NULL, alive, when);        LNET_UNLOCK();                lnet_do_notify(lp);                LNET_LOCK();        lnet_peer_decref_locked(lp);        LNET_UNLOCK();        return 0;}EXPORT_SYMBOL(lnet_notify);#elseintlnet_notify (lnet_ni_t *ni, lnet_nid_t nid, int alive, time_t when){        return -EOPNOTSUPP;}#endifstatic voidlnet_rtr_addref_locked(lnet_peer_t *lp){        LASSERT (lp->lp_refcount > 0);        LASSERT (lp->lp_rtr_refcount >= 0);        lp->lp_rtr_refcount++;        if (lp->lp_rtr_refcount == 1) {                struct list_head *pos;                /* a simple insertion sort */                list_for_each_prev(pos, &the_lnet.ln_routers) {                        lnet_peer_t *rtr = list_entry(pos, lnet_peer_t,                                                       lp_rtr_list);                        if (rtr->lp_nid < lp->lp_nid)                                break;                }                list_add(&lp->lp_rtr_list, pos);                /* addref for the_lnet.ln_routers */                lnet_peer_addref_locked(lp);                the_lnet.ln_routers_version++;        }}static voidlnet_rtr_decref_locked(lnet_peer_t *lp){        LASSERT (lp->lp_refcount > 0);        LASSERT (lp->lp_rtr_refcount > 0);        lp->lp_rtr_refcount--;        if (lp->lp_rtr_refcount == 0) {                list_del(&lp->lp_rtr_list);                /* decref for the_lnet.ln_routers */                lnet_peer_decref_locked(lp);                the_lnet.ln_routers_version++;        }}lnet_remotenet_t *lnet_find_net_locked (__u32 net){        lnet_remotenet_t *rnet;        struct list_head *tmp;        LASSERT (!the_lnet.ln_shutdown);        list_for_each (tmp, &the_lnet.ln_remote_nets) {                rnet = list_entry(tmp, lnet_remotenet_t, lrn_list);                if (rnet->lrn_net == net)                        return rnet;        }        return NULL;}intlnet_add_route (__u32 net, unsigned int hops, lnet_nid_t gateway){        struct list_head     zombies;	struct list_head    *e;	lnet_remotenet_t    *rnet;	lnet_remotenet_t    *rnet2;	lnet_route_t        *route;	lnet_route_t        *route2;        lnet_ni_t           *ni;        int                  add_route;        int                  rc;        CDEBUG(D_NET, "Add route: net %s hops %u gw %s\n",               libcfs_net2str(net), hops, libcfs_nid2str(gateway));        if (gateway == LNET_NID_ANY ||            LNET_NETTYP(LNET_NIDNET(gateway)) == LOLND ||            net == LNET_NIDNET(LNET_NID_ANY) ||            LNET_NETTYP(net) == LOLND ||            LNET_NIDNET(gateway) == net ||            hops < 1 || hops > 255)                return (-EINVAL);        if (lnet_islocalnet(net))               /* it's a local network */                return 0;                       /* ignore the route entry */        /* Assume net, route, all new */        LIBCFS_ALLOC(route, sizeof(*route));        LIBCFS_ALLOC(rnet, sizeof(*rnet));        if (route == NULL || rnet == NULL) {                CERROR("Out of memory creating route %s %d %s\n",                       libcfs_net2str(net), hops, libcfs_nid2str(gateway));                if (route != NULL)                        LIBCFS_FREE(route, sizeof(*route));                if (rnet != NULL)                        LIBCFS_FREE(rnet, sizeof(*rnet));                return -ENOMEM;        }        CFS_INIT_LIST_HEAD(&rnet->lrn_routes);        rnet->lrn_net = net;        rnet->lrn_hops = hops;        LNET_LOCK();        rc = lnet_nid2peer_locked(&route->lr_gateway, gateway);        if (rc != 0) {                LNET_UNLOCK();                LIBCFS_FREE(route, sizeof(*route));                LIBCFS_FREE(rnet, sizeof(*rnet));                if (rc == -EHOSTUNREACH)        /* gateway is not on a local net */                        return 0;               /* ignore the route entry */                CERROR("Error %d creating route %s %d %s\n", rc,                       libcfs_net2str(net), hops, libcfs_nid2str(gateway));                return rc;        }        LASSERT (!the_lnet.ln_shutdown);        CFS_INIT_LIST_HEAD(&zombies);        rnet2 = lnet_find_net_locked(net);        if (rnet2 == NULL) {                /* new network */                list_add_tail(&rnet->lrn_list, &the_lnet.ln_remote_nets);                rnet2 = rnet;        }        if (hops > rnet2->lrn_hops) {                /* New route is longer; ignore it */                add_route = 0;        } else if (hops < rnet2->lrn_hops) {                /* new route supercedes all currently known routes to this                 * net */                list_add(&zombies, &rnet2->lrn_routes);                list_del_init(&rnet2->lrn_routes);                add_route = 1;        } else {                add_route = 1;                /* New route has the same hopcount as existing routes; search                 * for a duplicate route (it's a NOOP if it is) */                list_for_each (e, &rnet2->lrn_routes) {                        route2 = list_entry(e, lnet_route_t, lr_list);                        if (route2->lr_gateway == route->lr_gateway) {                                add_route = 0;                                break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?