| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 | * net/tipc/bearer.c: TIPC bearer code | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 3 | * | 
| Per Liden | 593a5f2 | 2006-01-11 19:14:19 +0100 | [diff] [blame] | 4 | * Copyright (c) 1996-2006, Ericsson AB | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 5 | * Copyright (c) 2004-2006, 2010-2011, Wind River Systems | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 6 | * All rights reserved. | 
|  | 7 | * | 
| Per Liden | 9ea1fd3 | 2006-01-11 13:30:43 +0100 | [diff] [blame] | 8 | * Redistribution and use in source and binary forms, with or without | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 9 | * modification, are permitted provided that the following conditions are met: | 
|  | 10 | * | 
| Per Liden | 9ea1fd3 | 2006-01-11 13:30:43 +0100 | [diff] [blame] | 11 | * 1. Redistributions of source code must retain the above copyright | 
|  | 12 | *    notice, this list of conditions and the following disclaimer. | 
|  | 13 | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | 14 | *    notice, this list of conditions and the following disclaimer in the | 
|  | 15 | *    documentation and/or other materials provided with the distribution. | 
|  | 16 | * 3. Neither the names of the copyright holders nor the names of its | 
|  | 17 | *    contributors may be used to endorse or promote products derived from | 
|  | 18 | *    this software without specific prior written permission. | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 19 | * | 
| Per Liden | 9ea1fd3 | 2006-01-11 13:30:43 +0100 | [diff] [blame] | 20 | * Alternatively, this software may be distributed under the terms of the | 
|  | 21 | * GNU General Public License ("GPL") version 2 as published by the Free | 
|  | 22 | * Software Foundation. | 
|  | 23 | * | 
|  | 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
|  | 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
|  | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 
|  | 28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
|  | 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
|  | 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
|  | 32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
|  | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 34 | * POSSIBILITY OF SUCH DAMAGE. | 
|  | 35 | */ | 
|  | 36 |  | 
|  | 37 | #include "core.h" | 
|  | 38 | #include "config.h" | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 39 | #include "bearer.h" | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 40 | #include "discover.h" | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 41 |  | 
|  | 42 | #define MAX_ADDR_STR 32 | 
|  | 43 |  | 
| Paul Gortmaker | 358a0d1 | 2011-12-29 20:19:42 -0500 | [diff] [blame] | 44 | static struct tipc_media *media_list[MAX_MEDIA]; | 
| Allan Stephens | e3ec9c7 | 2010-12-31 18:59:34 +0000 | [diff] [blame] | 45 | static u32 media_count; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 46 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 47 | struct tipc_bearer tipc_bearers[MAX_BEARERS]; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 48 |  | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 49 | static void bearer_disable(struct tipc_bearer *b_ptr); | 
|  | 50 |  | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 51 | /** | 
|  | 52 | * media_name_valid - validate media name | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 53 | * | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 54 | * Returns 1 if media name is valid, otherwise 0. | 
|  | 55 | */ | 
|  | 56 |  | 
|  | 57 | static int media_name_valid(const char *name) | 
|  | 58 | { | 
|  | 59 | u32 len; | 
|  | 60 |  | 
|  | 61 | len = strlen(name); | 
|  | 62 | if ((len + 1) > TIPC_MAX_MEDIA_NAME) | 
|  | 63 | return 0; | 
| Eric Dumazet | a02cec2 | 2010-09-22 20:43:57 +0000 | [diff] [blame] | 64 | return strspn(name, tipc_alphabet) == len; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 65 | } | 
|  | 66 |  | 
|  | 67 | /** | 
| Allan Stephens | 5c216e1 | 2011-10-18 11:34:29 -0400 | [diff] [blame] | 68 | * tipc_media_find - locates specified media object by name | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 69 | */ | 
|  | 70 |  | 
| Paul Gortmaker | 358a0d1 | 2011-12-29 20:19:42 -0500 | [diff] [blame] | 71 | struct tipc_media *tipc_media_find(const char *name) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 72 | { | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 73 | u32 i; | 
|  | 74 |  | 
| Allan Stephens | a31abe8 | 2011-10-07 09:25:12 -0400 | [diff] [blame] | 75 | for (i = 0; i < media_count; i++) { | 
|  | 76 | if (!strcmp(media_list[i]->name, name)) | 
|  | 77 | return media_list[i]; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 78 | } | 
| Sam Ravnborg | 1fc54d8 | 2006-03-20 22:36:47 -0800 | [diff] [blame] | 79 | return NULL; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 80 | } | 
|  | 81 |  | 
|  | 82 | /** | 
| Allan Stephens | c79be45 | 2011-10-06 16:40:55 -0400 | [diff] [blame] | 83 | * media_find_id - locates specified media object by type identifier | 
|  | 84 | */ | 
|  | 85 |  | 
| Paul Gortmaker | 358a0d1 | 2011-12-29 20:19:42 -0500 | [diff] [blame] | 86 | static struct tipc_media *media_find_id(u8 type) | 
| Allan Stephens | c79be45 | 2011-10-06 16:40:55 -0400 | [diff] [blame] | 87 | { | 
|  | 88 | u32 i; | 
|  | 89 |  | 
|  | 90 | for (i = 0; i < media_count; i++) { | 
| Allan Stephens | a31abe8 | 2011-10-07 09:25:12 -0400 | [diff] [blame] | 91 | if (media_list[i]->type_id == type) | 
|  | 92 | return media_list[i]; | 
| Allan Stephens | c79be45 | 2011-10-06 16:40:55 -0400 | [diff] [blame] | 93 | } | 
|  | 94 | return NULL; | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | /** | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 98 | * tipc_register_media - register a media type | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 99 | * | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 100 | * Bearers for this media type must be activated separately at a later stage. | 
|  | 101 | */ | 
|  | 102 |  | 
| Paul Gortmaker | 358a0d1 | 2011-12-29 20:19:42 -0500 | [diff] [blame] | 103 | int tipc_register_media(struct tipc_media *m_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 104 | { | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 105 | int res = -EINVAL; | 
|  | 106 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 107 | write_lock_bh(&tipc_net_lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 108 |  | 
| Allan Stephens | 6c34921 | 2011-10-07 09:54:44 -0400 | [diff] [blame] | 109 | if (!media_name_valid(m_ptr->name)) | 
| Neil Horman | d0021b2 | 2010-03-03 08:31:23 +0000 | [diff] [blame] | 110 | goto exit; | 
| Allan Stephens | 3d749a6 | 2011-10-07 15:19:11 -0400 | [diff] [blame] | 111 | if ((m_ptr->bcast_addr.media_id != m_ptr->type_id) || | 
|  | 112 | !m_ptr->bcast_addr.broadcast) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 113 | goto exit; | 
| Allan Stephens | 6c34921 | 2011-10-07 09:54:44 -0400 | [diff] [blame] | 114 | if (m_ptr->priority > TIPC_MAX_LINK_PRI) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 115 | goto exit; | 
| Allan Stephens | 706767d | 2011-10-06 15:28:44 -0400 | [diff] [blame] | 116 | if ((m_ptr->tolerance < TIPC_MIN_LINK_TOL) || | 
| Allan Stephens | 6c34921 | 2011-10-07 09:54:44 -0400 | [diff] [blame] | 117 | (m_ptr->tolerance > TIPC_MAX_LINK_TOL)) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 118 | goto exit; | 
| Allan Stephens | 6c34921 | 2011-10-07 09:54:44 -0400 | [diff] [blame] | 119 | if (media_count >= MAX_MEDIA) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 120 | goto exit; | 
| Allan Stephens | 5c216e1 | 2011-10-18 11:34:29 -0400 | [diff] [blame] | 121 | if (tipc_media_find(m_ptr->name) || media_find_id(m_ptr->type_id)) | 
| Allan Stephens | c79be45 | 2011-10-06 16:40:55 -0400 | [diff] [blame] | 122 | goto exit; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 123 |  | 
| Allan Stephens | a31abe8 | 2011-10-07 09:25:12 -0400 | [diff] [blame] | 124 | media_list[media_count] = m_ptr; | 
| Allan Stephens | c79be45 | 2011-10-06 16:40:55 -0400 | [diff] [blame] | 125 | media_count++; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 126 | res = 0; | 
|  | 127 | exit: | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 128 | write_unlock_bh(&tipc_net_lock); | 
| Allan Stephens | 6c34921 | 2011-10-07 09:54:44 -0400 | [diff] [blame] | 129 | if (res) | 
|  | 130 | warn("Media <%s> registration error\n", m_ptr->name); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 131 | return res; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | /** | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 135 | * tipc_media_addr_printf - record media address in print buffer | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 136 | */ | 
|  | 137 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 138 | void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 139 | { | 
| Allan Stephens | c61b666 | 2011-10-07 11:31:49 -0400 | [diff] [blame] | 140 | char addr_str[MAX_ADDR_STR]; | 
| Paul Gortmaker | 358a0d1 | 2011-12-29 20:19:42 -0500 | [diff] [blame] | 141 | struct tipc_media *m_ptr; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 142 |  | 
| Allan Stephens | 3d749a6 | 2011-10-07 15:19:11 -0400 | [diff] [blame] | 143 | m_ptr = media_find_id(a->media_id); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 144 |  | 
| Allan Stephens | c61b666 | 2011-10-07 11:31:49 -0400 | [diff] [blame] | 145 | if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str))) | 
|  | 146 | tipc_printf(pb, "%s(%s)", m_ptr->name, addr_str); | 
|  | 147 | else { | 
| Allan Stephens | c61b666 | 2011-10-07 11:31:49 -0400 | [diff] [blame] | 148 | u32 i; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 149 |  | 
| Allan Stephens | 3d749a6 | 2011-10-07 15:19:11 -0400 | [diff] [blame] | 150 | tipc_printf(pb, "UNKNOWN(%u)", a->media_id); | 
|  | 151 | for (i = 0; i < sizeof(a->value); i++) | 
|  | 152 | tipc_printf(pb, "-%02x", a->value[i]); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 153 | } | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | /** | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 157 | * tipc_media_get_names - record names of registered media in buffer | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 158 | */ | 
|  | 159 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 160 | struct sk_buff *tipc_media_get_names(void) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 161 | { | 
|  | 162 | struct sk_buff *buf; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 163 | int i; | 
|  | 164 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 165 | buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME)); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 166 | if (!buf) | 
|  | 167 | return NULL; | 
|  | 168 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 169 | read_lock_bh(&tipc_net_lock); | 
| Allan Stephens | a31abe8 | 2011-10-07 09:25:12 -0400 | [diff] [blame] | 170 | for (i = 0; i < media_count; i++) { | 
|  | 171 | tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, | 
|  | 172 | media_list[i]->name, | 
|  | 173 | strlen(media_list[i]->name) + 1); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 174 | } | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 175 | read_unlock_bh(&tipc_net_lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 176 | return buf; | 
|  | 177 | } | 
|  | 178 |  | 
|  | 179 | /** | 
|  | 180 | * bearer_name_validate - validate & (optionally) deconstruct bearer name | 
|  | 181 | * @name - ptr to bearer name string | 
|  | 182 | * @name_parts - ptr to area for bearer name components (or NULL if not needed) | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 183 | * | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 184 | * Returns 1 if bearer name is valid, otherwise 0. | 
|  | 185 | */ | 
|  | 186 |  | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 187 | static int bearer_name_validate(const char *name, | 
| Paul Gortmaker | f19765f | 2011-12-29 21:39:49 -0500 | [diff] [blame] | 188 | struct tipc_bearer_names *name_parts) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 189 | { | 
|  | 190 | char name_copy[TIPC_MAX_BEARER_NAME]; | 
|  | 191 | char *media_name; | 
|  | 192 | char *if_name; | 
|  | 193 | u32 media_len; | 
|  | 194 | u32 if_len; | 
|  | 195 |  | 
|  | 196 | /* copy bearer name & ensure length is OK */ | 
|  | 197 |  | 
|  | 198 | name_copy[TIPC_MAX_BEARER_NAME - 1] = 0; | 
|  | 199 | /* need above in case non-Posix strncpy() doesn't pad with nulls */ | 
|  | 200 | strncpy(name_copy, name, TIPC_MAX_BEARER_NAME); | 
|  | 201 | if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0) | 
|  | 202 | return 0; | 
|  | 203 |  | 
|  | 204 | /* ensure all component parts of bearer name are present */ | 
|  | 205 |  | 
|  | 206 | media_name = name_copy; | 
| Allan Stephens | 2db9983 | 2010-12-31 18:59:33 +0000 | [diff] [blame] | 207 | if_name = strchr(media_name, ':'); | 
|  | 208 | if (if_name == NULL) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 209 | return 0; | 
|  | 210 | *(if_name++) = 0; | 
|  | 211 | media_len = if_name - media_name; | 
|  | 212 | if_len = strlen(if_name) + 1; | 
|  | 213 |  | 
|  | 214 | /* validate component parts of bearer name */ | 
|  | 215 |  | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 216 | if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || | 
|  | 217 | (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) || | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 218 | (strspn(media_name, tipc_alphabet) != (media_len - 1)) || | 
|  | 219 | (strspn(if_name, tipc_alphabet) != (if_len - 1))) | 
|  | 220 | return 0; | 
|  | 221 |  | 
|  | 222 | /* return bearer name components, if necessary */ | 
|  | 223 |  | 
|  | 224 | if (name_parts) { | 
|  | 225 | strcpy(name_parts->media_name, media_name); | 
|  | 226 | strcpy(name_parts->if_name, if_name); | 
|  | 227 | } | 
|  | 228 | return 1; | 
|  | 229 | } | 
|  | 230 |  | 
|  | 231 | /** | 
| Allan Stephens | 5c216e1 | 2011-10-18 11:34:29 -0400 | [diff] [blame] | 232 | * tipc_bearer_find - locates bearer object with matching bearer name | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 233 | */ | 
|  | 234 |  | 
| Allan Stephens | 5c216e1 | 2011-10-18 11:34:29 -0400 | [diff] [blame] | 235 | struct tipc_bearer *tipc_bearer_find(const char *name) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 236 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 237 | struct tipc_bearer *b_ptr; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 238 | u32 i; | 
|  | 239 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 240 | for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 241 | if (b_ptr->active && (!strcmp(b_ptr->name, name))) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 242 | return b_ptr; | 
|  | 243 | } | 
| Sam Ravnborg | 1fc54d8 | 2006-03-20 22:36:47 -0800 | [diff] [blame] | 244 | return NULL; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 245 | } | 
|  | 246 |  | 
|  | 247 | /** | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 248 | * tipc_bearer_find_interface - locates bearer object with matching interface name | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 249 | */ | 
|  | 250 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 251 | struct tipc_bearer *tipc_bearer_find_interface(const char *if_name) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 252 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 253 | struct tipc_bearer *b_ptr; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 254 | char *b_if_name; | 
|  | 255 | u32 i; | 
|  | 256 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 257 | for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 258 | if (!b_ptr->active) | 
|  | 259 | continue; | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 260 | b_if_name = strchr(b_ptr->name, ':') + 1; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 261 | if (!strcmp(b_if_name, if_name)) | 
|  | 262 | return b_ptr; | 
|  | 263 | } | 
| Sam Ravnborg | 1fc54d8 | 2006-03-20 22:36:47 -0800 | [diff] [blame] | 264 | return NULL; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 265 | } | 
|  | 266 |  | 
|  | 267 | /** | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 268 | * tipc_bearer_get_names - record names of bearers in buffer | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 269 | */ | 
|  | 270 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 271 | struct sk_buff *tipc_bearer_get_names(void) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 272 | { | 
|  | 273 | struct sk_buff *buf; | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 274 | struct tipc_bearer *b_ptr; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 275 | int i, j; | 
|  | 276 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 277 | buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 278 | if (!buf) | 
|  | 279 | return NULL; | 
|  | 280 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 281 | read_lock_bh(&tipc_net_lock); | 
| Allan Stephens | a31abe8 | 2011-10-07 09:25:12 -0400 | [diff] [blame] | 282 | for (i = 0; i < media_count; i++) { | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 283 | for (j = 0; j < MAX_BEARERS; j++) { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 284 | b_ptr = &tipc_bearers[j]; | 
| Allan Stephens | a31abe8 | 2011-10-07 09:25:12 -0400 | [diff] [blame] | 285 | if (b_ptr->active && (b_ptr->media == media_list[i])) { | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 286 | tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 287 | b_ptr->name, | 
|  | 288 | strlen(b_ptr->name) + 1); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 289 | } | 
|  | 290 | } | 
|  | 291 | } | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 292 | read_unlock_bh(&tipc_net_lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 293 | return buf; | 
|  | 294 | } | 
|  | 295 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 296 | void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 297 | { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 298 | tipc_nmap_add(&b_ptr->nodes, dest); | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 299 | tipc_bcbearer_sort(); | 
| Allan Stephens | 1209966 | 2011-04-21 19:05:25 -0500 | [diff] [blame] | 300 | tipc_disc_add_dest(b_ptr->link_req); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 301 | } | 
|  | 302 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 303 | void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 304 | { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 305 | tipc_nmap_remove(&b_ptr->nodes, dest); | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 306 | tipc_bcbearer_sort(); | 
| Allan Stephens | 1209966 | 2011-04-21 19:05:25 -0500 | [diff] [blame] | 307 | tipc_disc_remove_dest(b_ptr->link_req); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 308 | } | 
|  | 309 |  | 
|  | 310 | /* | 
|  | 311 | * bearer_push(): Resolve bearer congestion. Force the waiting | 
|  | 312 | * links to push out their unsent packets, one packet per link | 
|  | 313 | * per iteration, until all packets are gone or congestion reoccurs. | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 314 | * 'tipc_net_lock' is read_locked when this function is called | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 315 | * bearer.lock must be taken before calling | 
|  | 316 | * Returns binary true(1) ore false(0) | 
|  | 317 | */ | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 318 | static int bearer_push(struct tipc_bearer *b_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 319 | { | 
| Allan Stephens | 0e35fd5 | 2008-07-14 22:44:01 -0700 | [diff] [blame] | 320 | u32 res = 0; | 
| Paul Gortmaker | a18c4bc | 2011-12-29 20:58:42 -0500 | [diff] [blame] | 321 | struct tipc_link *ln, *tln; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 322 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 323 | if (b_ptr->blocked) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 324 | return 0; | 
|  | 325 |  | 
|  | 326 | while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { | 
|  | 327 | list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 328 | res = tipc_link_push_packet(ln); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 329 | if (res == PUSH_FAILED) | 
|  | 330 | break; | 
|  | 331 | if (res == PUSH_FINISHED) | 
|  | 332 | list_move_tail(&ln->link_list, &b_ptr->links); | 
|  | 333 | } | 
|  | 334 | } | 
|  | 335 | return list_empty(&b_ptr->cong_links); | 
|  | 336 | } | 
|  | 337 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 338 | void tipc_bearer_lock_push(struct tipc_bearer *b_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 339 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 340 | spin_lock_bh(&b_ptr->lock); | 
| Allan Stephens | 23f0ff9 | 2011-04-07 11:25:26 -0400 | [diff] [blame] | 341 | bearer_push(b_ptr); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 342 | spin_unlock_bh(&b_ptr->lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 343 | } | 
|  | 344 |  | 
|  | 345 |  | 
|  | 346 | /* | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 347 | * Interrupt enabling new requests after bearer congestion or blocking: | 
|  | 348 | * See bearer_send(). | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 349 | */ | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 350 | void tipc_continue(struct tipc_bearer *b_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 351 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 352 | spin_lock_bh(&b_ptr->lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 353 | if (!list_empty(&b_ptr->cong_links)) | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 354 | tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 355 | b_ptr->blocked = 0; | 
|  | 356 | spin_unlock_bh(&b_ptr->lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 357 | } | 
|  | 358 |  | 
|  | 359 | /* | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 360 | * Schedule link for sending of messages after the bearer | 
|  | 361 | * has been deblocked by 'continue()'. This method is called | 
|  | 362 | * when somebody tries to send a message via this link while | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 363 | * the bearer is congested. 'tipc_net_lock' is in read_lock here | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 364 | * bearer.lock is busy | 
|  | 365 | */ | 
|  | 366 |  | 
| Paul Gortmaker | a18c4bc | 2011-12-29 20:58:42 -0500 | [diff] [blame] | 367 | static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr, | 
|  | 368 | struct tipc_link *l_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 369 | { | 
|  | 370 | list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); | 
|  | 371 | } | 
|  | 372 |  | 
|  | 373 | /* | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 374 | * Schedule link for sending of messages after the bearer | 
|  | 375 | * has been deblocked by 'continue()'. This method is called | 
|  | 376 | * when somebody tries to send a message via this link while | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 377 | * the bearer is congested. 'tipc_net_lock' is in read_lock here, | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 378 | * bearer.lock is free | 
|  | 379 | */ | 
|  | 380 |  | 
| Paul Gortmaker | a18c4bc | 2011-12-29 20:58:42 -0500 | [diff] [blame] | 381 | void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 382 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 383 | spin_lock_bh(&b_ptr->lock); | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 384 | tipc_bearer_schedule_unlocked(b_ptr, l_ptr); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 385 | spin_unlock_bh(&b_ptr->lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 386 | } | 
|  | 387 |  | 
|  | 388 |  | 
|  | 389 | /* | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 390 | * tipc_bearer_resolve_congestion(): Check if there is bearer congestion, | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 391 | * and if there is, try to resolve it before returning. | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 392 | * 'tipc_net_lock' is read_locked when this function is called | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 393 | */ | 
| Paul Gortmaker | a18c4bc | 2011-12-29 20:58:42 -0500 | [diff] [blame] | 394 | int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, | 
|  | 395 | struct tipc_link *l_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 396 | { | 
|  | 397 | int res = 1; | 
|  | 398 |  | 
|  | 399 | if (list_empty(&b_ptr->cong_links)) | 
|  | 400 | return 1; | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 401 | spin_lock_bh(&b_ptr->lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 402 | if (!bearer_push(b_ptr)) { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 403 | tipc_bearer_schedule_unlocked(b_ptr, l_ptr); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 404 | res = 0; | 
|  | 405 | } | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 406 | spin_unlock_bh(&b_ptr->lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 407 | return res; | 
|  | 408 | } | 
|  | 409 |  | 
| Allan Stephens | b274f4a | 2010-05-11 14:30:16 +0000 | [diff] [blame] | 410 | /** | 
|  | 411 | * tipc_bearer_congested - determines if bearer is currently congested | 
|  | 412 | */ | 
|  | 413 |  | 
| Paul Gortmaker | a18c4bc | 2011-12-29 20:58:42 -0500 | [diff] [blame] | 414 | int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr) | 
| Allan Stephens | b274f4a | 2010-05-11 14:30:16 +0000 | [diff] [blame] | 415 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 416 | if (unlikely(b_ptr->blocked)) | 
| Allan Stephens | b274f4a | 2010-05-11 14:30:16 +0000 | [diff] [blame] | 417 | return 1; | 
|  | 418 | if (likely(list_empty(&b_ptr->cong_links))) | 
|  | 419 | return 0; | 
|  | 420 | return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); | 
|  | 421 | } | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 422 |  | 
|  | 423 | /** | 
|  | 424 | * tipc_enable_bearer - enable bearer with the given name | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 425 | */ | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 426 |  | 
| Allan Stephens | 50d3e63 | 2011-02-28 14:56:15 -0500 | [diff] [blame] | 427 | int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 428 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 429 | struct tipc_bearer *b_ptr; | 
| Paul Gortmaker | 358a0d1 | 2011-12-29 20:19:42 -0500 | [diff] [blame] | 430 | struct tipc_media *m_ptr; | 
| Paul Gortmaker | f19765f | 2011-12-29 21:39:49 -0500 | [diff] [blame] | 431 | struct tipc_bearer_names b_names; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 432 | char addr_string[16]; | 
|  | 433 | u32 bearer_id; | 
|  | 434 | u32 with_this_prio; | 
|  | 435 | u32 i; | 
|  | 436 | int res = -EINVAL; | 
|  | 437 |  | 
| Allan Stephens | b58343f | 2011-11-08 13:48:28 -0500 | [diff] [blame] | 438 | if (!tipc_own_addr) { | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 439 | warn("Bearer <%s> rejected, not supported in standalone mode\n", | 
|  | 440 | name); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 441 | return -ENOPROTOOPT; | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 442 | } | 
| Paul Gortmaker | f19765f | 2011-12-29 21:39:49 -0500 | [diff] [blame] | 443 | if (!bearer_name_validate(name, &b_names)) { | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 444 | warn("Bearer <%s> rejected, illegal name\n", name); | 
| Per Liden | 16cb4b3 | 2006-01-13 22:22:22 +0100 | [diff] [blame] | 445 | return -EINVAL; | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 446 | } | 
| Allan Stephens | 66e019a | 2011-04-20 16:24:07 -0500 | [diff] [blame] | 447 | if (tipc_addr_domain_valid(disc_domain) && | 
|  | 448 | (disc_domain != tipc_own_addr)) { | 
|  | 449 | if (tipc_in_scope(disc_domain, tipc_own_addr)) { | 
|  | 450 | disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK; | 
|  | 451 | res = 0;   /* accept any node in own cluster */ | 
|  | 452 | } else if (in_own_cluster(disc_domain)) | 
|  | 453 | res = 0;   /* accept specified node in own cluster */ | 
|  | 454 | } | 
|  | 455 | if (res) { | 
| Allan Stephens | 50d3e63 | 2011-02-28 14:56:15 -0500 | [diff] [blame] | 456 | warn("Bearer <%s> rejected, illegal discovery domain\n", name); | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 457 | return -EINVAL; | 
|  | 458 | } | 
| Allan Stephens | 9efde4a | 2011-11-03 13:15:10 -0400 | [diff] [blame] | 459 | if ((priority > TIPC_MAX_LINK_PRI) && | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 460 | (priority != TIPC_MEDIA_LINK_PRI)) { | 
|  | 461 | warn("Bearer <%s> rejected, illegal priority\n", name); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 462 | return -EINVAL; | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 463 | } | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 464 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 465 | write_lock_bh(&tipc_net_lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 466 |  | 
| Paul Gortmaker | f19765f | 2011-12-29 21:39:49 -0500 | [diff] [blame] | 467 | m_ptr = tipc_media_find(b_names.media_name); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 468 | if (!m_ptr) { | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 469 | warn("Bearer <%s> rejected, media <%s> not registered\n", name, | 
| Paul Gortmaker | f19765f | 2011-12-29 21:39:49 -0500 | [diff] [blame] | 470 | b_names.media_name); | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 471 | goto exit; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 472 | } | 
| Per Liden | 16cb4b3 | 2006-01-13 22:22:22 +0100 | [diff] [blame] | 473 |  | 
|  | 474 | if (priority == TIPC_MEDIA_LINK_PRI) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 475 | priority = m_ptr->priority; | 
|  | 476 |  | 
|  | 477 | restart: | 
|  | 478 | bearer_id = MAX_BEARERS; | 
|  | 479 | with_this_prio = 1; | 
|  | 480 | for (i = MAX_BEARERS; i-- != 0; ) { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 481 | if (!tipc_bearers[i].active) { | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 482 | bearer_id = i; | 
|  | 483 | continue; | 
|  | 484 | } | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 485 | if (!strcmp(name, tipc_bearers[i].name)) { | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 486 | warn("Bearer <%s> rejected, already enabled\n", name); | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 487 | goto exit; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 488 | } | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 489 | if ((tipc_bearers[i].priority == priority) && | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 490 | (++with_this_prio > 2)) { | 
|  | 491 | if (priority-- == 0) { | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 492 | warn("Bearer <%s> rejected, duplicate priority\n", | 
|  | 493 | name); | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 494 | goto exit; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 495 | } | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 496 | warn("Bearer <%s> priority adjustment required %u->%u\n", | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 497 | name, priority + 1, priority); | 
|  | 498 | goto restart; | 
|  | 499 | } | 
|  | 500 | } | 
|  | 501 | if (bearer_id >= MAX_BEARERS) { | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 502 | warn("Bearer <%s> rejected, bearer limit reached (%u)\n", | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 503 | name, MAX_BEARERS); | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 504 | goto exit; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 505 | } | 
|  | 506 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 507 | b_ptr = &tipc_bearers[bearer_id]; | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 508 | strcpy(b_ptr->name, name); | 
|  | 509 | res = m_ptr->enable_bearer(b_ptr); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 510 | if (res) { | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 511 | warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 512 | goto exit; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 513 | } | 
|  | 514 |  | 
|  | 515 | b_ptr->identity = bearer_id; | 
|  | 516 | b_ptr->media = m_ptr; | 
| Allan Stephens | 5c216e1 | 2011-10-18 11:34:29 -0400 | [diff] [blame] | 517 | b_ptr->tolerance = m_ptr->tolerance; | 
|  | 518 | b_ptr->window = m_ptr->window; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 519 | b_ptr->net_plane = bearer_id + 'A'; | 
|  | 520 | b_ptr->active = 1; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 521 | b_ptr->priority = priority; | 
|  | 522 | INIT_LIST_HEAD(&b_ptr->cong_links); | 
|  | 523 | INIT_LIST_HEAD(&b_ptr->links); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 524 | spin_lock_init(&b_ptr->lock); | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 525 |  | 
|  | 526 | res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain); | 
|  | 527 | if (res) { | 
|  | 528 | bearer_disable(b_ptr); | 
|  | 529 | warn("Bearer <%s> rejected, discovery object creation failed\n", | 
|  | 530 | name); | 
|  | 531 | goto exit; | 
|  | 532 | } | 
| Per Liden | 16cb4b3 | 2006-01-13 22:22:22 +0100 | [diff] [blame] | 533 | info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 
| Allan Stephens | 50d3e63 | 2011-02-28 14:56:15 -0500 | [diff] [blame] | 534 | name, tipc_addr_string_fill(addr_string, disc_domain), priority); | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 535 | exit: | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 536 | write_unlock_bh(&tipc_net_lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 537 | return res; | 
|  | 538 | } | 
|  | 539 |  | 
|  | 540 | /** | 
|  | 541 | * tipc_block_bearer(): Block the bearer with the given name, | 
|  | 542 | *                      and reset all its links | 
|  | 543 | */ | 
|  | 544 |  | 
|  | 545 | int tipc_block_bearer(const char *name) | 
|  | 546 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 547 | struct tipc_bearer *b_ptr = NULL; | 
| Paul Gortmaker | a18c4bc | 2011-12-29 20:58:42 -0500 | [diff] [blame] | 548 | struct tipc_link *l_ptr; | 
|  | 549 | struct tipc_link *temp_l_ptr; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 550 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 551 | read_lock_bh(&tipc_net_lock); | 
| Allan Stephens | 5c216e1 | 2011-10-18 11:34:29 -0400 | [diff] [blame] | 552 | b_ptr = tipc_bearer_find(name); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 553 | if (!b_ptr) { | 
|  | 554 | warn("Attempt to block unknown bearer <%s>\n", name); | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 555 | read_unlock_bh(&tipc_net_lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 556 | return -EINVAL; | 
|  | 557 | } | 
|  | 558 |  | 
| Allan Stephens | a10bd92 | 2006-06-25 23:52:17 -0700 | [diff] [blame] | 559 | info("Blocking bearer <%s>\n", name); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 560 | spin_lock_bh(&b_ptr->lock); | 
|  | 561 | b_ptr->blocked = 1; | 
| Allan Stephens | 4b3743e | 2011-05-26 13:59:17 -0400 | [diff] [blame] | 562 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 563 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 
| David S. Miller | 6c00055 | 2008-09-02 23:38:32 -0700 | [diff] [blame] | 564 | struct tipc_node *n_ptr = l_ptr->owner; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 565 |  | 
|  | 566 | spin_lock_bh(&n_ptr->lock); | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 567 | tipc_link_reset(l_ptr); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 568 | spin_unlock_bh(&n_ptr->lock); | 
|  | 569 | } | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 570 | spin_unlock_bh(&b_ptr->lock); | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 571 | read_unlock_bh(&tipc_net_lock); | 
| Allan Stephens | 0e35fd5 | 2008-07-14 22:44:01 -0700 | [diff] [blame] | 572 | return 0; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 573 | } | 
|  | 574 |  | 
|  | 575 | /** | 
|  | 576 | * bearer_disable - | 
| YOSHIFUJI Hideaki | c430728 | 2007-02-09 23:25:21 +0900 | [diff] [blame] | 577 | * | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 578 | * Note: This routine assumes caller holds tipc_net_lock. | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 579 | */ | 
|  | 580 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 581 | static void bearer_disable(struct tipc_bearer *b_ptr) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 582 | { | 
| Paul Gortmaker | a18c4bc | 2011-12-29 20:58:42 -0500 | [diff] [blame] | 583 | struct tipc_link *l_ptr; | 
|  | 584 | struct tipc_link *temp_l_ptr; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 585 |  | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 586 | info("Disabling bearer <%s>\n", b_ptr->name); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 587 | spin_lock_bh(&b_ptr->lock); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 588 | b_ptr->blocked = 1; | 
|  | 589 | b_ptr->media->disable_bearer(b_ptr); | 
| Allan Stephens | 4b3743e | 2011-05-26 13:59:17 -0400 | [diff] [blame] | 590 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 591 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 592 | tipc_link_delete(l_ptr); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 593 | } | 
| Allan Stephens | 3a777ff | 2011-04-21 13:58:26 -0500 | [diff] [blame] | 594 | if (b_ptr->link_req) | 
|  | 595 | tipc_disc_delete(b_ptr->link_req); | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 596 | spin_unlock_bh(&b_ptr->lock); | 
|  | 597 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 598 | } | 
|  | 599 |  | 
|  | 600 | int tipc_disable_bearer(const char *name) | 
|  | 601 | { | 
| Allan Stephens | 2d627b9 | 2011-01-07 13:00:11 -0500 | [diff] [blame] | 602 | struct tipc_bearer *b_ptr; | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 603 | int res; | 
|  | 604 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 605 | write_lock_bh(&tipc_net_lock); | 
| Allan Stephens | 5c216e1 | 2011-10-18 11:34:29 -0400 | [diff] [blame] | 606 | b_ptr = tipc_bearer_find(name); | 
| Allan Stephens | ccc901e | 2010-10-14 13:58:26 +0000 | [diff] [blame] | 607 | if (b_ptr == NULL) { | 
|  | 608 | warn("Attempt to disable unknown bearer <%s>\n", name); | 
|  | 609 | res = -EINVAL; | 
| Allan Stephens | 28cc937 | 2010-11-30 12:00:56 +0000 | [diff] [blame] | 610 | } else { | 
|  | 611 | bearer_disable(b_ptr); | 
|  | 612 | res = 0; | 
|  | 613 | } | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 614 | write_unlock_bh(&tipc_net_lock); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 615 | return res; | 
|  | 616 | } | 
|  | 617 |  | 
|  | 618 |  | 
|  | 619 |  | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 620 | void tipc_bearer_stop(void) | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 621 | { | 
|  | 622 | u32 i; | 
|  | 623 |  | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 624 | for (i = 0; i < MAX_BEARERS; i++) { | 
| Per Liden | 4323add | 2006-01-18 00:38:21 +0100 | [diff] [blame] | 625 | if (tipc_bearers[i].active) | 
| Allan Stephens | ccc901e | 2010-10-14 13:58:26 +0000 | [diff] [blame] | 626 | bearer_disable(&tipc_bearers[i]); | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 627 | } | 
| Per Liden | b97bf3f | 2006-01-02 19:04:38 +0100 | [diff] [blame] | 628 | media_count = 0; | 
|  | 629 | } |