mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 11:16:11 +00:00
[TIPC] Initial merge
TIPC (Transparent Inter Process Communication) is a protocol designed for intra cluster communication. For more information see http://tipc.sourceforge.net Signed-off-by: Per Liden <per.liden@nospam.ericsson.com>
This commit is contained in:
parent
58cba4650a
commit
b97bf3fd8f
54 changed files with 19464 additions and 0 deletions
|
@ -186,6 +186,7 @@ struct ucred {
|
|||
#define AF_PPPOX 24 /* PPPoX sockets */
|
||||
#define AF_WANPIPE 25 /* Wanpipe API Sockets */
|
||||
#define AF_LLC 26 /* Linux LLC */
|
||||
#define AF_TIPC 30 /* TIPC sockets */
|
||||
#define AF_BLUETOOTH 31 /* Bluetooth sockets */
|
||||
#define AF_MAX 32 /* For now.. */
|
||||
|
||||
|
@ -218,6 +219,7 @@ struct ucred {
|
|||
#define PF_PPPOX AF_PPPOX
|
||||
#define PF_WANPIPE AF_WANPIPE
|
||||
#define PF_LLC AF_LLC
|
||||
#define PF_TIPC AF_TIPC
|
||||
#define PF_BLUETOOTH AF_BLUETOOTH
|
||||
#define PF_MAX AF_MAX
|
||||
|
||||
|
@ -279,6 +281,7 @@ struct ucred {
|
|||
#define SOL_LLC 268
|
||||
#define SOL_DCCP 269
|
||||
#define SOL_NETLINK 270
|
||||
#define SOL_TIPC 271
|
||||
|
||||
/* IPX options */
|
||||
#define IPX_TYPE 1
|
||||
|
|
598
include/linux/tipc.h
Normal file
598
include/linux/tipc.h
Normal file
|
@ -0,0 +1,598 @@
|
|||
/*
|
||||
* include/linux/tipc.h: Include file for TIPC users
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_TIPC_H_
|
||||
#define _LINUX_TIPC_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
/*
|
||||
* TIPC addressing primitives
|
||||
*/
|
||||
|
||||
struct tipc_portid {
|
||||
__u32 ref;
|
||||
__u32 node;
|
||||
};
|
||||
|
||||
struct tipc_name {
|
||||
__u32 type;
|
||||
__u32 instance;
|
||||
};
|
||||
|
||||
struct tipc_name_seq {
|
||||
__u32 type;
|
||||
__u32 lower;
|
||||
__u32 upper;
|
||||
};
|
||||
|
||||
static inline __u32 tipc_addr(unsigned int zone,
|
||||
unsigned int cluster,
|
||||
unsigned int node)
|
||||
{
|
||||
return(zone << 24) | (cluster << 12) | node;
|
||||
}
|
||||
|
||||
static inline unsigned int tipc_zone(__u32 addr)
|
||||
{
|
||||
return addr >> 24;
|
||||
}
|
||||
|
||||
static inline unsigned int tipc_cluster(__u32 addr)
|
||||
{
|
||||
return(addr >> 12) & 0xfff;
|
||||
}
|
||||
|
||||
static inline unsigned int tipc_node(__u32 addr)
|
||||
{
|
||||
return addr & 0xfff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Application-accessible port name types
|
||||
*/
|
||||
|
||||
#define TIPC_NET_EVENTS 0 /* network event subscription name type */
|
||||
#define TIPC_TOP_SRV 1 /* topology service name type */
|
||||
#define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */
|
||||
|
||||
/*
|
||||
* Publication scopes when binding port names and port name sequences
|
||||
*/
|
||||
|
||||
#define TIPC_ZONE_SCOPE 1
|
||||
#define TIPC_CLUSTER_SCOPE 2
|
||||
#define TIPC_NODE_SCOPE 3
|
||||
|
||||
/*
|
||||
* Limiting values for messages
|
||||
*/
|
||||
|
||||
#define TIPC_MAX_USER_MSG_SIZE 66000
|
||||
|
||||
/*
|
||||
* Message importance levels
|
||||
*/
|
||||
|
||||
#define TIPC_LOW_IMPORTANCE 0 /* default */
|
||||
#define TIPC_MEDIUM_IMPORTANCE 1
|
||||
#define TIPC_HIGH_IMPORTANCE 2
|
||||
#define TIPC_CRITICAL_IMPORTANCE 3
|
||||
|
||||
/*
|
||||
* Msg rejection/connection shutdown reasons
|
||||
*/
|
||||
|
||||
#define TIPC_OK 0
|
||||
#define TIPC_ERR_NO_NAME 1
|
||||
#define TIPC_ERR_NO_PORT 2
|
||||
#define TIPC_ERR_NO_NODE 3
|
||||
#define TIPC_ERR_OVERLOAD 4
|
||||
#define TIPC_CONN_SHUTDOWN 5
|
||||
|
||||
/*
|
||||
* TIPC topology subscription service definitions
|
||||
*/
|
||||
|
||||
#define TIPC_SUB_PORTS 0x01 /* filter for port availability */
|
||||
#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */
|
||||
#if 0
|
||||
/* The following filter options are not currently implemented */
|
||||
#define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */
|
||||
#define TIPC_SUB_NO_UNBIND_EVTS 0x08 /* filter out "withdraw" events */
|
||||
#define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */
|
||||
#endif
|
||||
|
||||
#define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */
|
||||
|
||||
struct tipc_subscr {
|
||||
struct tipc_name_seq seq; /* name sequence of interest */
|
||||
__u32 timeout; /* subscription duration (in ms) */
|
||||
__u32 filter; /* bitmask of filter options */
|
||||
char usr_handle[8]; /* available for subscriber use */
|
||||
};
|
||||
|
||||
|
||||
#define TIPC_PUBLISHED 1 /* publication event */
|
||||
#define TIPC_WITHDRAWN 2 /* withdraw event */
|
||||
#define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */
|
||||
|
||||
struct tipc_event {
|
||||
__u32 event; /* event type */
|
||||
__u32 found_lower; /* matching name seq instances */
|
||||
__u32 found_upper; /* " " " " */
|
||||
struct tipc_portid port; /* associated port */
|
||||
struct tipc_subscr s; /* associated subscription */
|
||||
};
|
||||
|
||||
/*
|
||||
* Socket API
|
||||
*/
|
||||
|
||||
#ifndef AF_TIPC
|
||||
#define AF_TIPC 30
|
||||
#endif
|
||||
|
||||
#ifndef PF_TIPC
|
||||
#define PF_TIPC AF_TIPC
|
||||
#endif
|
||||
|
||||
#ifndef SOL_TIPC
|
||||
#define SOL_TIPC 271
|
||||
#endif
|
||||
|
||||
#define TIPC_ADDR_NAMESEQ 1
|
||||
#define TIPC_ADDR_MCAST 1
|
||||
#define TIPC_ADDR_NAME 2
|
||||
#define TIPC_ADDR_ID 3
|
||||
|
||||
struct sockaddr_tipc {
|
||||
unsigned short family;
|
||||
unsigned char addrtype;
|
||||
signed char scope;
|
||||
union {
|
||||
struct tipc_portid id;
|
||||
struct tipc_name_seq nameseq;
|
||||
struct {
|
||||
struct tipc_name name;
|
||||
__u32 domain; /* 0: own zone */
|
||||
} name;
|
||||
} addr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Ancillary data objects supported by recvmsg()
|
||||
*/
|
||||
|
||||
#define TIPC_ERRINFO 1 /* error info */
|
||||
#define TIPC_RETDATA 2 /* returned data */
|
||||
#define TIPC_DESTNAME 3 /* destination name */
|
||||
|
||||
/*
|
||||
* TIPC-specific socket option values
|
||||
*/
|
||||
|
||||
#define TIPC_IMPORTANCE 127 /* Default: TIPC_LOW_IMPORTANCE */
|
||||
#define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */
|
||||
#define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */
|
||||
#define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */
|
||||
|
||||
/*
|
||||
* Bearer
|
||||
*/
|
||||
|
||||
/* Identifiers of supported TIPC media types */
|
||||
|
||||
#define TIPC_MEDIA_TYPE_ETH 1
|
||||
|
||||
/* Maximum sizes of TIPC bearer-related names (including terminating NUL) */
|
||||
|
||||
#define TIPC_MAX_MEDIA_NAME 16 /* format = media */
|
||||
#define TIPC_MAX_IF_NAME 16 /* format = interface */
|
||||
#define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */
|
||||
#define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */
|
||||
|
||||
struct tipc_media_addr {
|
||||
__u32 type;
|
||||
union {
|
||||
__u8 eth_addr[6]; /* Ethernet bearer */
|
||||
#if 0
|
||||
/* Prototypes for other possible bearer types */
|
||||
|
||||
struct {
|
||||
__u16 sin_family;
|
||||
__u16 sin_port;
|
||||
struct {
|
||||
__u32 s_addr;
|
||||
} sin_addr;
|
||||
char pad[4];
|
||||
} addr_in; /* IP-based bearer */
|
||||
__u16 sock_descr; /* generic socket bearer */
|
||||
#endif
|
||||
} dev_addr;
|
||||
};
|
||||
|
||||
|
||||
/* Link priority limits (range from 0 to # priorities - 1) */
|
||||
|
||||
#define TIPC_NUM_LINK_PRI 32
|
||||
|
||||
/* Link tolerance limits (min, default, max), in ms */
|
||||
|
||||
#define TIPC_MIN_LINK_TOL 50
|
||||
#define TIPC_DEF_LINK_TOL 1500
|
||||
#define TIPC_MAX_LINK_TOL 30000
|
||||
|
||||
/* Link window limits (min, default, max), in packets */
|
||||
|
||||
#define TIPC_MIN_LINK_WIN 16
|
||||
#define TIPC_DEF_LINK_WIN 50
|
||||
#define TIPC_MAX_LINK_WIN 150
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*
|
||||
* All configuration management messaging involves sending a request message
|
||||
* to the TIPC configuration service on a node, which sends a reply message
|
||||
* back. (In the future multi-message replies may be supported.)
|
||||
*
|
||||
* Both request and reply messages consist of a transport header and payload.
|
||||
* The transport header contains info about the desired operation;
|
||||
* the payload consists of zero or more type/length/value (TLV) items
|
||||
* which specify parameters or results for the operation.
|
||||
*
|
||||
* For many operations, the request and reply messages have a fixed number
|
||||
* of TLVs (usually zero or one); however, some reply messages may return
|
||||
* a variable number of TLVs. A failed request is denoted by the presence
|
||||
* of an "error string" TLV in the reply message instead of the TLV(s) the
|
||||
* reply should contain if the request succeeds.
|
||||
*/
|
||||
|
||||
#define TIPC_CFG_SRV 0 /* configuration service name type */
|
||||
|
||||
/*
|
||||
* Public commands:
|
||||
* May be issued by any process.
|
||||
* Accepted by own node, or by remote node only if remote management enabled.
|
||||
*/
|
||||
|
||||
#define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */
|
||||
#define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */
|
||||
#define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */
|
||||
#define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */
|
||||
#define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */
|
||||
#define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */
|
||||
#define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */
|
||||
#define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */
|
||||
|
||||
#if 0
|
||||
#define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */
|
||||
#define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */
|
||||
#define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */
|
||||
#define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Protected commands:
|
||||
* May only be issued by "network administration capable" process.
|
||||
* Accepted by own node, or by remote node only if remote management enabled
|
||||
* and this node is zone manager.
|
||||
*/
|
||||
|
||||
#define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */
|
||||
#define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */
|
||||
|
||||
#define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */
|
||||
#define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */
|
||||
#define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */
|
||||
#define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */
|
||||
#define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */
|
||||
#define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */
|
||||
#define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */
|
||||
|
||||
#if 0
|
||||
#define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */
|
||||
#define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */
|
||||
#define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */
|
||||
#define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Private commands:
|
||||
* May only be issued by "network administration capable" process.
|
||||
* Accepted by own node only; cannot be used on a remote node.
|
||||
*/
|
||||
|
||||
#define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */
|
||||
#if 0
|
||||
#define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */
|
||||
#endif
|
||||
#define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */
|
||||
#define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */
|
||||
|
||||
/*
|
||||
* TLV types defined for TIPC
|
||||
*/
|
||||
|
||||
#define TIPC_TLV_NONE 0 /* no TLV present */
|
||||
#define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/
|
||||
#define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */
|
||||
#define TIPC_TLV_STRING 3 /* char[128] (max) */
|
||||
#define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */
|
||||
#define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */
|
||||
|
||||
#define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */
|
||||
#define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting <Z.C.N> */
|
||||
#define TIPC_TLV_MEDIA_NAME 18 /* char[MAX_MEDIA_NAME] */
|
||||
#define TIPC_TLV_BEARER_NAME 19 /* char[MAX_BEARER_NAME] */
|
||||
#define TIPC_TLV_LINK_NAME 20 /* char[MAX_LINK_NAME] */
|
||||
#define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */
|
||||
#define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */
|
||||
#define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */
|
||||
#define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */
|
||||
#define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */
|
||||
#define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */
|
||||
|
||||
struct tipc_node_info {
|
||||
__u32 addr; /* network address of node */
|
||||
__u32 up; /* 0=down, 1= up */
|
||||
};
|
||||
|
||||
struct tipc_link_info {
|
||||
__u32 dest; /* network address of peer node */
|
||||
__u32 up; /* 0=down, 1=up */
|
||||
char str[TIPC_MAX_LINK_NAME]; /* link name */
|
||||
};
|
||||
|
||||
struct tipc_bearer_config {
|
||||
__u32 priority; /* Range [1,31]. Override per link */
|
||||
__u32 detect_scope;
|
||||
char name[TIPC_MAX_BEARER_NAME];
|
||||
};
|
||||
|
||||
struct tipc_link_config {
|
||||
__u32 value;
|
||||
char name[TIPC_MAX_LINK_NAME];
|
||||
};
|
||||
|
||||
#define TIPC_NTQ_ALLTYPES 0x80000000
|
||||
|
||||
struct tipc_name_table_query {
|
||||
__u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */
|
||||
__u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */
|
||||
__u32 lowbound; /* (i.e. displays all entries of name table) */
|
||||
__u32 upbound;
|
||||
};
|
||||
|
||||
/*
|
||||
* The error string TLV is a null-terminated string describing the cause
|
||||
* of the request failure. To simplify error processing (and to save space)
|
||||
* the first character of the string can be a special error code character
|
||||
* (lying by the range 0x80 to 0xFF) which represents a pre-defined reason.
|
||||
*/
|
||||
|
||||
#define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */
|
||||
#define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */
|
||||
#define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */
|
||||
#define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */
|
||||
#define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */
|
||||
#define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */
|
||||
|
||||
#if 0
|
||||
/* prototypes TLV structures for proposed commands */
|
||||
struct tipc_link_create {
|
||||
__u32 domain;
|
||||
struct tipc_media_addr peer_addr;
|
||||
char bearer_name[MAX_BEARER_NAME];
|
||||
};
|
||||
|
||||
struct tipc_route_info {
|
||||
__u32 dest;
|
||||
__u32 router;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A TLV consists of a descriptor, followed by the TLV value.
|
||||
* TLV descriptor fields are stored in network byte order;
|
||||
* TLV values must also be stored in network byte order (where applicable).
|
||||
* TLV descriptors must be aligned to addresses which are multiple of 4,
|
||||
* so up to 3 bytes of padding may exist at the end of the TLV value area.
|
||||
* There must not be any padding between the TLV descriptor and its value.
|
||||
*/
|
||||
|
||||
struct tlv_desc {
|
||||
__u16 tlv_len; /* TLV length (descriptor + value) */
|
||||
__u16 tlv_type; /* TLV identifier */
|
||||
};
|
||||
|
||||
#define TLV_ALIGNTO 4
|
||||
|
||||
#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1))
|
||||
#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen))
|
||||
#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen)))
|
||||
#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0)))
|
||||
|
||||
static inline int TLV_OK(const void *tlv, __u16 space)
|
||||
{
|
||||
/*
|
||||
* Would also like to check that "tlv" is a multiple of 4,
|
||||
* but don't know how to do this in a portable way.
|
||||
* - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler
|
||||
* won't allow binary "&" with a pointer.
|
||||
* - Tried casting "tlv" to integer type, but causes warning about size
|
||||
* mismatch when pointer is bigger than chosen type (int, long, ...).
|
||||
*/
|
||||
|
||||
return (space >= TLV_SPACE(0)) &&
|
||||
(ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space);
|
||||
}
|
||||
|
||||
static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type)
|
||||
{
|
||||
return TLV_OK(tlv, space) &&
|
||||
(ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type);
|
||||
}
|
||||
|
||||
static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len)
|
||||
{
|
||||
struct tlv_desc *tlv_ptr;
|
||||
int tlv_len;
|
||||
|
||||
tlv_len = TLV_LENGTH(len);
|
||||
tlv_ptr = (struct tlv_desc *)tlv;
|
||||
tlv_ptr->tlv_type = htons(type);
|
||||
tlv_ptr->tlv_len = htons(tlv_len);
|
||||
if (len && data)
|
||||
memcpy(TLV_DATA(tlv_ptr), data, tlv_len);
|
||||
return TLV_SPACE(len);
|
||||
}
|
||||
|
||||
/*
|
||||
* A TLV list descriptor simplifies processing of messages
|
||||
* containing multiple TLVs.
|
||||
*/
|
||||
|
||||
struct tlv_list_desc {
|
||||
struct tlv_desc *tlv_ptr; /* ptr to current TLV */
|
||||
__u32 tlv_space; /* # bytes from curr TLV to list end */
|
||||
};
|
||||
|
||||
static inline void TLV_LIST_INIT(struct tlv_list_desc *list,
|
||||
void *data, __u32 space)
|
||||
{
|
||||
list->tlv_ptr = (struct tlv_desc *)data;
|
||||
list->tlv_space = space;
|
||||
}
|
||||
|
||||
static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list)
|
||||
{
|
||||
return (list->tlv_space == 0);
|
||||
}
|
||||
|
||||
static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type)
|
||||
{
|
||||
return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type);
|
||||
}
|
||||
|
||||
static inline void *TLV_LIST_DATA(struct tlv_list_desc *list)
|
||||
{
|
||||
return TLV_DATA(list->tlv_ptr);
|
||||
}
|
||||
|
||||
static inline void TLV_LIST_STEP(struct tlv_list_desc *list)
|
||||
{
|
||||
__u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len));
|
||||
|
||||
list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space);
|
||||
list->tlv_space -= tlv_space;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configuration messages exchanged via NETLINK_GENERIC use the following
|
||||
* family id, name, version and command.
|
||||
*/
|
||||
#define TIPC_GENL_FAMILY 0x222
|
||||
#define TIPC_GENL_NAME "TIPC"
|
||||
#define TIPC_GENL_VERSION 0x1
|
||||
#define TIPC_GENL_CMD 0x1
|
||||
|
||||
/*
|
||||
* TIPC specific header used in NETLINK_GENERIC requests.
|
||||
*/
|
||||
struct tipc_genlmsghdr {
|
||||
__u32 dest; /* Destination address */
|
||||
__u16 cmd; /* Command */
|
||||
__u16 reserved; /* Unused */
|
||||
};
|
||||
|
||||
#define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr))
|
||||
|
||||
/*
|
||||
* Configuration messages exchanged via TIPC sockets use the TIPC configuration
|
||||
* message header, which is defined below. This structure is analogous
|
||||
* to the Netlink message header, but fields are stored in network byte order
|
||||
* and no padding is permitted between the header and the message data
|
||||
* that follows.
|
||||
*/
|
||||
|
||||
struct tipc_cfg_msg_hdr
|
||||
{
|
||||
__u32 tcm_len; /* Message length (including header) */
|
||||
__u16 tcm_type; /* Command type */
|
||||
__u16 tcm_flags; /* Additional flags */
|
||||
char tcm_reserved[8]; /* Unused */
|
||||
};
|
||||
|
||||
#define TCM_F_REQUEST 0x1 /* Flag: Request message */
|
||||
#define TCM_F_MORE 0x2 /* Flag: Message to be continued */
|
||||
|
||||
#define TCM_ALIGN(datalen) (((datalen)+3) & ~3)
|
||||
#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen)
|
||||
#define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen)))
|
||||
#define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0)))
|
||||
|
||||
static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags,
|
||||
void *data, __u16 data_len)
|
||||
{
|
||||
struct tipc_cfg_msg_hdr *tcm_hdr;
|
||||
int msg_len;
|
||||
|
||||
msg_len = TCM_LENGTH(data_len);
|
||||
tcm_hdr = (struct tipc_cfg_msg_hdr *)msg;
|
||||
tcm_hdr->tcm_len = htonl(msg_len);
|
||||
tcm_hdr->tcm_type = htons(cmd);
|
||||
tcm_hdr->tcm_flags = htons(flags);
|
||||
if (data_len && data)
|
||||
memcpy(TCM_DATA(msg), data, data_len);
|
||||
return TCM_SPACE(data_len);
|
||||
}
|
||||
|
||||
#endif
|
255
include/net/tipc/tipc.h
Normal file
255
include/net/tipc/tipc.h
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* include/net/tipc/tipc.h: Main include file for TIPC users
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NET_TIPC_H_
|
||||
#define _NET_TIPC_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/tipc.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
/*
|
||||
* Native API
|
||||
* ----------
|
||||
*/
|
||||
|
||||
/*
|
||||
* TIPC operating mode routines
|
||||
*/
|
||||
|
||||
u32 tipc_get_addr(void);
|
||||
|
||||
#define TIPC_NOT_RUNNING 0
|
||||
#define TIPC_NODE_MODE 1
|
||||
#define TIPC_NET_MODE 2
|
||||
|
||||
typedef void (*tipc_mode_event)(void *usr_handle, int mode, u32 addr);
|
||||
|
||||
int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle);
|
||||
|
||||
void tipc_detach(unsigned int userref);
|
||||
|
||||
int tipc_get_mode(void);
|
||||
|
||||
/*
|
||||
* TIPC port manipulation routines
|
||||
*/
|
||||
|
||||
typedef void (*tipc_msg_err_event) (void *usr_handle,
|
||||
u32 portref,
|
||||
struct sk_buff **buf,
|
||||
unsigned char const *data,
|
||||
unsigned int size,
|
||||
int reason,
|
||||
struct tipc_portid const *attmpt_destid);
|
||||
|
||||
typedef void (*tipc_named_msg_err_event) (void *usr_handle,
|
||||
u32 portref,
|
||||
struct sk_buff **buf,
|
||||
unsigned char const *data,
|
||||
unsigned int size,
|
||||
int reason,
|
||||
struct tipc_name_seq const *attmpt_dest);
|
||||
|
||||
typedef void (*tipc_conn_shutdown_event) (void *usr_handle,
|
||||
u32 portref,
|
||||
struct sk_buff **buf,
|
||||
unsigned char const *data,
|
||||
unsigned int size,
|
||||
int reason);
|
||||
|
||||
typedef void (*tipc_msg_event) (void *usr_handle,
|
||||
u32 portref,
|
||||
struct sk_buff **buf,
|
||||
unsigned char const *data,
|
||||
unsigned int size,
|
||||
unsigned int importance,
|
||||
struct tipc_portid const *origin);
|
||||
|
||||
typedef void (*tipc_named_msg_event) (void *usr_handle,
|
||||
u32 portref,
|
||||
struct sk_buff **buf,
|
||||
unsigned char const *data,
|
||||
unsigned int size,
|
||||
unsigned int importance,
|
||||
struct tipc_portid const *orig,
|
||||
struct tipc_name_seq const *dest);
|
||||
|
||||
typedef void (*tipc_conn_msg_event) (void *usr_handle,
|
||||
u32 portref,
|
||||
struct sk_buff **buf,
|
||||
unsigned char const *data,
|
||||
unsigned int size);
|
||||
|
||||
typedef void (*tipc_continue_event) (void *usr_handle,
|
||||
u32 portref);
|
||||
|
||||
int tipc_createport(unsigned int tipc_user,
|
||||
void *usr_handle,
|
||||
unsigned int importance,
|
||||
tipc_msg_err_event error_cb,
|
||||
tipc_named_msg_err_event named_error_cb,
|
||||
tipc_conn_shutdown_event conn_error_cb,
|
||||
tipc_msg_event message_cb,
|
||||
tipc_named_msg_event named_message_cb,
|
||||
tipc_conn_msg_event conn_message_cb,
|
||||
tipc_continue_event continue_event_cb,/* May be zero */
|
||||
u32 *portref);
|
||||
|
||||
int tipc_deleteport(u32 portref);
|
||||
|
||||
int tipc_ownidentity(u32 portref, struct tipc_portid *port);
|
||||
|
||||
int tipc_portimportance(u32 portref, unsigned int *importance);
|
||||
int tipc_set_portimportance(u32 portref, unsigned int importance);
|
||||
|
||||
int tipc_portunreliable(u32 portref, unsigned int *isunreliable);
|
||||
int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
|
||||
|
||||
int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
|
||||
int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
|
||||
|
||||
int tipc_publish(u32 portref, unsigned int scope,
|
||||
struct tipc_name_seq const *name_seq);
|
||||
int tipc_withdraw(u32 portref, unsigned int scope,
|
||||
struct tipc_name_seq const *name_seq); /* 0: all */
|
||||
|
||||
int tipc_connect2port(u32 portref, struct tipc_portid const *port);
|
||||
|
||||
int tipc_disconnect(u32 portref);
|
||||
|
||||
int tipc_shutdown(u32 ref); /* Sends SHUTDOWN msg */
|
||||
|
||||
int tipc_isconnected(u32 portref, int *isconnected);
|
||||
|
||||
int tipc_peer(u32 portref, struct tipc_portid *peer);
|
||||
|
||||
int tipc_ref_valid(u32 portref);
|
||||
|
||||
/*
|
||||
* TIPC messaging routines
|
||||
*/
|
||||
|
||||
#define TIPC_PORT_IMPORTANCE 100 /* send using current port setting */
|
||||
|
||||
|
||||
int tipc_send(u32 portref,
|
||||
unsigned int num_sect,
|
||||
struct iovec const *msg_sect);
|
||||
|
||||
int tipc_send_buf(u32 portref,
|
||||
struct sk_buff *buf,
|
||||
unsigned int dsz);
|
||||
|
||||
int tipc_send2name(u32 portref,
|
||||
struct tipc_name const *name,
|
||||
u32 domain, /* 0:own zone */
|
||||
unsigned int num_sect,
|
||||
struct iovec const *msg_sect);
|
||||
|
||||
int tipc_send_buf2name(u32 portref,
|
||||
struct tipc_name const *name,
|
||||
u32 domain,
|
||||
struct sk_buff *buf,
|
||||
unsigned int dsz);
|
||||
|
||||
int tipc_forward2name(u32 portref,
|
||||
struct tipc_name const *name,
|
||||
u32 domain, /*0: own zone */
|
||||
unsigned int section_count,
|
||||
struct iovec const *msg_sect,
|
||||
struct tipc_portid const *origin,
|
||||
unsigned int importance);
|
||||
|
||||
int tipc_forward_buf2name(u32 portref,
|
||||
struct tipc_name const *name,
|
||||
u32 domain,
|
||||
struct sk_buff *buf,
|
||||
unsigned int dsz,
|
||||
struct tipc_portid const *orig,
|
||||
unsigned int importance);
|
||||
|
||||
int tipc_send2port(u32 portref,
|
||||
struct tipc_portid const *dest,
|
||||
unsigned int num_sect,
|
||||
struct iovec const *msg_sect);
|
||||
|
||||
int tipc_send_buf2port(u32 portref,
|
||||
struct tipc_portid const *dest,
|
||||
struct sk_buff *buf,
|
||||
unsigned int dsz);
|
||||
|
||||
int tipc_forward2port(u32 portref,
|
||||
struct tipc_portid const *dest,
|
||||
unsigned int num_sect,
|
||||
struct iovec const *msg_sect,
|
||||
struct tipc_portid const *origin,
|
||||
unsigned int importance);
|
||||
|
||||
int tipc_forward_buf2port(u32 portref,
|
||||
struct tipc_portid const *dest,
|
||||
struct sk_buff *buf,
|
||||
unsigned int dsz,
|
||||
struct tipc_portid const *orig,
|
||||
unsigned int importance);
|
||||
|
||||
int tipc_multicast(u32 portref,
|
||||
struct tipc_name_seq const *seq,
|
||||
u32 domain, /* 0:own zone */
|
||||
unsigned int section_count,
|
||||
struct iovec const *msg);
|
||||
|
||||
#if 0
|
||||
int tipc_multicast_buf(u32 portref,
|
||||
struct tipc_name_seq const *seq,
|
||||
u32 domain, /* 0:own zone */
|
||||
void *buf,
|
||||
unsigned int size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TIPC subscription routines
|
||||
*/
|
||||
|
||||
int tipc_ispublished(struct tipc_name const *name);
|
||||
|
||||
/*
|
||||
* Get number of available nodes within specified domain (excluding own node)
|
||||
*/
|
||||
|
||||
unsigned int tipc_available_nodes(const u32 domain);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
92
include/net/tipc/tipc_bearer.h
Normal file
92
include/net/tipc/tipc_bearer.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* include/net/tipc/tipc_bearer.h: Include file for privileged access to TIPC bearers
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NET_TIPC_BEARER_H_
|
||||
#define _NET_TIPC_BEARER_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/tipc.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
/**
|
||||
* struct tipc_bearer - TIPC bearer info available to privileged users
|
||||
* @usr_handle: pointer to additional user-defined information about bearer
|
||||
* @mtu: max packet size bearer can support
|
||||
* @blocked: non-zero if bearer is blocked
|
||||
* @lock: spinlock for controlling access to bearer
|
||||
* @addr: media-specific address associated with bearer
|
||||
* @name: bearer name (format = media:interface)
|
||||
*
|
||||
* Note: TIPC initializes "name" and "lock" fields; user is responsible for
|
||||
* initialization all other fields when a bearer is enabled.
|
||||
*/
|
||||
|
||||
struct tipc_bearer {
|
||||
void *usr_handle;
|
||||
u32 mtu;
|
||||
int blocked;
|
||||
spinlock_t lock;
|
||||
struct tipc_media_addr addr;
|
||||
char name[TIPC_MAX_BEARER_NAME];
|
||||
};
|
||||
|
||||
|
||||
int tipc_register_media(u32 media_type,
|
||||
char *media_name,
|
||||
int (*enable)(struct tipc_bearer *),
|
||||
void (*disable)(struct tipc_bearer *),
|
||||
int (*send_msg)(struct sk_buff *,
|
||||
struct tipc_bearer *,
|
||||
struct tipc_media_addr *),
|
||||
char *(*addr2str)(struct tipc_media_addr *a,
|
||||
char *str_buf,
|
||||
int str_size),
|
||||
struct tipc_media_addr *bcast_addr,
|
||||
const u32 bearer_priority,
|
||||
const u32 link_tolerance, /* [ms] */
|
||||
const u32 send_window_limit);
|
||||
|
||||
void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
|
||||
|
||||
int tipc_block_bearer(const char *name);
|
||||
void tipc_continue(struct tipc_bearer *tb_ptr);
|
||||
|
||||
int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);
|
||||
int tipc_disable_bearer(const char *name);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
220
include/net/tipc/tipc_msg.h
Normal file
220
include/net/tipc/tipc_msg.h
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* include/net/tipc/tipc_msg.h: Include file for privileged access to TIPC message headers
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NET_TIPC_MSG_H_
|
||||
#define _NET_TIPC_MSG_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct tipc_msg {
|
||||
u32 hdr[15];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
TIPC user data message header format, version 2:
|
||||
|
||||
|
||||
1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w0:|vers | user |hdr sz |n|d|s|-| message size |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w2:| link level ack no | broadcast/link level seq no |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w3:| previous node |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w4:| originating port |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w5:| destination port |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w6:| originating node |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w7:| destination node |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w8:| name type / transport sequence number |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w9:| name instance/multicast lower bound |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
wA:| multicast upper bound |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
/ /
|
||||
\ options \
|
||||
/ /
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
*/
|
||||
|
||||
#define TIPC_CONN_MSG 0
|
||||
#define TIPC_MCAST_MSG 1
|
||||
#define TIPC_NAMED_MSG 2
|
||||
#define TIPC_DIRECT_MSG 3
|
||||
|
||||
|
||||
static inline u32 msg_word(struct tipc_msg *m, u32 pos)
|
||||
{
|
||||
return ntohl(m->hdr[pos]);
|
||||
}
|
||||
|
||||
static inline u32 msg_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask)
|
||||
{
|
||||
return (msg_word(m, w) >> pos) & mask;
|
||||
}
|
||||
|
||||
static inline u32 msg_importance(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 25, 0xf);
|
||||
}
|
||||
|
||||
static inline u32 msg_hdr_sz(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 21, 0xf) << 2;
|
||||
}
|
||||
|
||||
static inline int msg_short(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_hdr_sz(m) == 24);
|
||||
}
|
||||
|
||||
static inline u32 msg_size(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 0, 0x1ffff);
|
||||
}
|
||||
|
||||
static inline u32 msg_data_sz(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_size(m) - msg_hdr_sz(m));
|
||||
}
|
||||
|
||||
static inline unchar *msg_data(struct tipc_msg *m)
|
||||
{
|
||||
return ((unchar *)m) + msg_hdr_sz(m);
|
||||
}
|
||||
|
||||
static inline u32 msg_type(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 1, 29, 0x7);
|
||||
}
|
||||
|
||||
static inline u32 msg_direct(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_type(m) == TIPC_DIRECT_MSG);
|
||||
}
|
||||
|
||||
static inline u32 msg_named(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_type(m) == TIPC_NAMED_MSG);
|
||||
}
|
||||
|
||||
static inline u32 msg_mcast(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_type(m) == TIPC_MCAST_MSG);
|
||||
}
|
||||
|
||||
static inline u32 msg_connected(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_type(m) == TIPC_CONN_MSG);
|
||||
}
|
||||
|
||||
static inline u32 msg_errcode(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 1, 25, 0xf);
|
||||
}
|
||||
|
||||
static inline u32 msg_prevnode(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 3);
|
||||
}
|
||||
|
||||
static inline u32 msg_origport(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 4);
|
||||
}
|
||||
|
||||
static inline u32 msg_destport(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 5);
|
||||
}
|
||||
|
||||
static inline u32 msg_mc_netid(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 5);
|
||||
}
|
||||
|
||||
static inline u32 msg_orignode(struct tipc_msg *m)
|
||||
{
|
||||
if (likely(msg_short(m)))
|
||||
return msg_prevnode(m);
|
||||
return msg_word(m, 6);
|
||||
}
|
||||
|
||||
static inline u32 msg_destnode(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 7);
|
||||
}
|
||||
|
||||
static inline u32 msg_nametype(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 8);
|
||||
}
|
||||
|
||||
static inline u32 msg_nameinst(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 9);
|
||||
}
|
||||
|
||||
static inline u32 msg_namelower(struct tipc_msg *m)
|
||||
{
|
||||
return msg_nameinst(m);
|
||||
}
|
||||
|
||||
static inline u32 msg_nameupper(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 10);
|
||||
}
|
||||
|
||||
static inline char *msg_options(struct tipc_msg *m, u32 *len)
|
||||
{
|
||||
u32 pos = msg_bits(m, 1, 16, 0x7);
|
||||
|
||||
if (!pos)
|
||||
return 0;
|
||||
pos = (pos * 4) + 28;
|
||||
*len = msg_hdr_sz(m) - pos;
|
||||
return (char *)&m->hdr[pos/4];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
105
include/net/tipc/tipc_port.h
Normal file
105
include/net/tipc/tipc_port.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NET_TIPC_PORT_H_
|
||||
#define _NET_TIPC_PORT_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/tipc.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/tipc/tipc_msg.h>
|
||||
|
||||
#define TIPC_FLOW_CONTROL_WIN 512
|
||||
|
||||
/**
|
||||
* struct tipc_port - native TIPC port info available to privileged users
|
||||
* @usr_handle: pointer to additional user-defined information about port
|
||||
* @lock: pointer to spinlock for controlling access to port
|
||||
* @connected: non-zero if port is currently connected to a peer port
|
||||
* @conn_type: TIPC type used when connection was established
|
||||
* @conn_instance: TIPC instance used when connection was established
|
||||
* @conn_unacked: number of unacknowledged messages received from peer port
|
||||
* @published: non-zero if port has one or more associated names
|
||||
* @congested: non-zero if cannot send because of link or port congestion
|
||||
* @ref: unique reference to port in TIPC object registry
|
||||
* @phdr: preformatted message header used when sending messages
|
||||
*/
|
||||
|
||||
struct tipc_port {
|
||||
void *usr_handle;
|
||||
spinlock_t *lock;
|
||||
int connected;
|
||||
u32 conn_type;
|
||||
u32 conn_instance;
|
||||
u32 conn_unacked;
|
||||
int published;
|
||||
u32 congested;
|
||||
u32 ref;
|
||||
struct tipc_msg phdr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* tipc_createport_raw - create a native TIPC port and return it's reference
|
||||
*
|
||||
* Note: 'dispatcher' and 'wakeup' deliver a locked port.
|
||||
*/
|
||||
|
||||
u32 tipc_createport_raw(void *usr_handle,
|
||||
u32 (*dispatcher)(struct tipc_port *, struct sk_buff *),
|
||||
void (*wakeup)(struct tipc_port *),
|
||||
const u32 importance);
|
||||
|
||||
/*
|
||||
* tipc_set_msg_option(): port must be locked.
|
||||
*/
|
||||
int tipc_set_msg_option(struct tipc_port *tp_ptr,
|
||||
const char *opt,
|
||||
const u32 len);
|
||||
|
||||
int tipc_reject_msg(struct sk_buff *buf, u32 err);
|
||||
|
||||
int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode);
|
||||
|
||||
void tipc_acknowledge(u32 port_ref,u32 ack);
|
||||
|
||||
struct tipc_port *tipc_get_port(const u32 ref);
|
||||
|
||||
void *tipc_get_handle(const u32 ref);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -159,6 +159,7 @@ source "net/ipx/Kconfig"
|
|||
source "drivers/net/appletalk/Kconfig"
|
||||
source "net/x25/Kconfig"
|
||||
source "net/lapb/Kconfig"
|
||||
source "net/tipc/Kconfig"
|
||||
|
||||
config NET_DIVERT
|
||||
bool "Frame Diverter (EXPERIMENTAL)"
|
||||
|
|
|
@ -45,6 +45,7 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q/
|
|||
obj-$(CONFIG_IP_DCCP) += dccp/
|
||||
obj-$(CONFIG_IP_SCTP) += sctp/
|
||||
obj-$(CONFIG_IEEE80211) += ieee80211/
|
||||
obj-$(CONFIG_TIPC) += tipc/
|
||||
|
||||
ifeq ($(CONFIG_NET),y)
|
||||
obj-$(CONFIG_SYSCTL) += sysctl_net.o
|
||||
|
|
112
net/tipc/Kconfig
Normal file
112
net/tipc/Kconfig
Normal file
|
@ -0,0 +1,112 @@
|
|||
#
|
||||
# TIPC configuration
|
||||
#
|
||||
|
||||
menu "TIPC Configuration (EXPERIMENTAL)"
|
||||
depends on INET && EXPERIMENTAL
|
||||
|
||||
config TIPC
|
||||
tristate "The TIPC Protocol (EXPERIMENTAL)"
|
||||
---help---
|
||||
TBD.
|
||||
|
||||
This protocol support is also available as a module ( = code which
|
||||
can be inserted in and removed from the running kernel whenever you
|
||||
want). The module will be called tipc. If you want to compile it
|
||||
as a module, say M here and read <file:Documentation/modules.txt>.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config TIPC_ADVANCED
|
||||
bool "TIPC: Advanced configuration"
|
||||
depends on TIPC
|
||||
default n
|
||||
help
|
||||
Saying Y here will open some advanced configuration
|
||||
for TIPC. Most users do not need to bother, so if
|
||||
unsure, just say N.
|
||||
|
||||
config TIPC_ZONES
|
||||
int "Maximum number of zones in network"
|
||||
depends on TIPC && TIPC_ADVANCED
|
||||
default "3"
|
||||
help
|
||||
Max number of zones inside TIPC network. Max supported value
|
||||
is 255 zones, minimum is 1
|
||||
|
||||
Default is 3 zones in a network; setting this to higher
|
||||
allows more zones but might use more memory.
|
||||
|
||||
config TIPC_CLUSTERS
|
||||
int "Maximum number of clusters in a zone"
|
||||
depends on TIPC && TIPC_ADVANCED
|
||||
default "1"
|
||||
help
|
||||
***Only 1 (one cluster in a zone) is supported by current code.
|
||||
Any value set here will be overridden.***
|
||||
|
||||
(Max number of clusters inside TIPC zone. Max supported
|
||||
value is 4095 clusters, minimum is 1.
|
||||
|
||||
Default is 1; setting this to smaller value might save
|
||||
some memory, setting it to higher
|
||||
allows more clusters and might consume more memory.)
|
||||
|
||||
config TIPC_NODES
|
||||
int "Maximum number of nodes in cluster"
|
||||
depends on TIPC && TIPC_ADVANCED
|
||||
default "255"
|
||||
help
|
||||
Maximum number of nodes inside a TIPC cluster. Maximum
|
||||
supported value is 2047 nodes, minimum is 8.
|
||||
|
||||
Setting this to a smaller value saves some memory,
|
||||
setting it to higher allows more nodes.
|
||||
|
||||
config TIPC_SLAVE_NODES
|
||||
int "Maximum number of slave nodes in cluster"
|
||||
depends on TIPC && TIPC_ADVANCED
|
||||
default "0"
|
||||
help
|
||||
***This capability is not supported by current code.***
|
||||
|
||||
Maximum number of slave nodes inside a TIPC cluster. Maximum
|
||||
supported value is 2047 nodes, minimum is 0.
|
||||
|
||||
Setting this to a smaller value saves some memory,
|
||||
setting it to higher allows more nodes.
|
||||
|
||||
config TIPC_PORTS
|
||||
int "Maximum number of ports in a node"
|
||||
depends on TIPC && TIPC_ADVANCED
|
||||
default "8191"
|
||||
help
|
||||
Maximum number of ports within a node. Maximum
|
||||
supported value is 64535 nodes, minimum is 127.
|
||||
|
||||
Setting this to a smaller value saves some memory,
|
||||
setting it to higher allows more ports.
|
||||
|
||||
config TIPC_LOG
|
||||
int "Size of log buffer"
|
||||
depends on TIPC && TIPC_ADVANCED
|
||||
default 0
|
||||
help
|
||||
Size (in bytes) of TIPC's internal log buffer, which records the
|
||||
occurrence of significant events. Maximum supported value
|
||||
is 32768 bytes, minimum is 0.
|
||||
|
||||
There is no need to enable the log buffer unless the node will be
|
||||
managed remotely via TIPC.
|
||||
|
||||
config TIPC_DEBUG
|
||||
bool "Enable debugging support"
|
||||
depends on TIPC
|
||||
default n
|
||||
help
|
||||
This will enable debugging of TIPC.
|
||||
|
||||
Only say Y here if you are having trouble with TIPC. It will
|
||||
enable the display of detailed information about what is going on.
|
||||
|
||||
endmenu
|
13
net/tipc/Makefile
Normal file
13
net/tipc/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Makefile for the Linux TIPC layer
|
||||
#
|
||||
|
||||
obj-$(CONFIG_TIPC) := tipc.o
|
||||
|
||||
tipc-y += addr.o bcast.o bearer.o config.o cluster.o \
|
||||
core.o handler.o link.o discover.o msg.o \
|
||||
name_distr.o subscr.o name_table.o net.o \
|
||||
netlink.o node.o node_subscr.o port.o ref.o \
|
||||
socket.o user_reg.o zone.o dbg.o eth_media.o
|
||||
|
||||
# End of file
|
91
net/tipc/addr.c
Normal file
91
net/tipc/addr.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* net/tipc/addr.c: TIPC address utility routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "dbg.h"
|
||||
#include "addr.h"
|
||||
#include "zone.h"
|
||||
#include "cluster.h"
|
||||
#include "net.h"
|
||||
|
||||
u32 tipc_get_addr(void)
|
||||
{
|
||||
return tipc_own_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* addr_domain_valid - validates a network domain address
|
||||
*
|
||||
* Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>,
|
||||
* where Z, C, and N are non-zero and do not exceed the configured limits.
|
||||
*
|
||||
* Returns 1 if domain address is valid, otherwise 0
|
||||
*/
|
||||
|
||||
int addr_domain_valid(u32 addr)
|
||||
{
|
||||
u32 n = tipc_node(addr);
|
||||
u32 c = tipc_cluster(addr);
|
||||
u32 z = tipc_zone(addr);
|
||||
u32 max_nodes = tipc_max_nodes;
|
||||
|
||||
if (is_slave(addr))
|
||||
max_nodes = LOWEST_SLAVE + tipc_max_slaves;
|
||||
if (n > max_nodes)
|
||||
return 0;
|
||||
if (c > tipc_max_clusters)
|
||||
return 0;
|
||||
if (z > tipc_max_zones)
|
||||
return 0;
|
||||
|
||||
if (n && (!z || !c))
|
||||
return 0;
|
||||
if (c && !z)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* addr_node_valid - validates a proposed network address for this node
|
||||
*
|
||||
* Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed
|
||||
* the configured limits.
|
||||
*
|
||||
* Returns 1 if address can be used, otherwise 0
|
||||
*/
|
||||
|
||||
int addr_node_valid(u32 addr)
|
||||
{
|
||||
return (addr_domain_valid(addr) && tipc_node(addr));
|
||||
}
|
||||
|
125
net/tipc/addr.h
Normal file
125
net/tipc/addr.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* net/tipc/addr.h: Include file for TIPC address utility routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_ADDR_H
|
||||
#define _TIPC_ADDR_H
|
||||
|
||||
static inline u32 own_node(void)
|
||||
{
|
||||
return tipc_node(tipc_own_addr);
|
||||
}
|
||||
|
||||
static inline u32 own_cluster(void)
|
||||
{
|
||||
return tipc_cluster(tipc_own_addr);
|
||||
}
|
||||
|
||||
static inline u32 own_zone(void)
|
||||
{
|
||||
return tipc_zone(tipc_own_addr);
|
||||
}
|
||||
|
||||
static inline int in_own_cluster(u32 addr)
|
||||
{
|
||||
return !((addr ^ tipc_own_addr) >> 12);
|
||||
}
|
||||
|
||||
static inline int in_own_zone(u32 addr)
|
||||
{
|
||||
return !((addr ^ tipc_own_addr) >> 24);
|
||||
}
|
||||
|
||||
static inline int is_slave(u32 addr)
|
||||
{
|
||||
return addr & 0x800;
|
||||
}
|
||||
|
||||
static inline int may_route(u32 addr)
|
||||
{
|
||||
return(addr ^ tipc_own_addr) >> 11;
|
||||
}
|
||||
|
||||
static inline int in_scope(u32 domain, u32 addr)
|
||||
{
|
||||
if (!domain || (domain == addr))
|
||||
return 1;
|
||||
if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */
|
||||
return 1;
|
||||
if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* addr_scope - convert message lookup domain to equivalent 2-bit scope value
|
||||
*/
|
||||
|
||||
static inline int addr_scope(u32 domain)
|
||||
{
|
||||
if (likely(!domain))
|
||||
return TIPC_ZONE_SCOPE;
|
||||
if (tipc_node(domain))
|
||||
return TIPC_NODE_SCOPE;
|
||||
if (tipc_cluster(domain))
|
||||
return TIPC_CLUSTER_SCOPE;
|
||||
return TIPC_ZONE_SCOPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* addr_domain - convert 2-bit scope value to equivalent message lookup domain
|
||||
*
|
||||
* Needed when address of a named message must be looked up a second time
|
||||
* after a network hop.
|
||||
*/
|
||||
|
||||
static inline int addr_domain(int sc)
|
||||
{
|
||||
if (likely(sc == TIPC_NODE_SCOPE))
|
||||
return tipc_own_addr;
|
||||
if (sc == TIPC_CLUSTER_SCOPE)
|
||||
return tipc_addr(tipc_zone(tipc_own_addr),
|
||||
tipc_cluster(tipc_own_addr), 0);
|
||||
return tipc_addr(tipc_zone(tipc_own_addr), 0, 0);
|
||||
}
|
||||
|
||||
static inline char *addr_string_fill(char *string, u32 addr)
|
||||
{
|
||||
snprintf(string, 16, "<%u.%u.%u>",
|
||||
tipc_zone(addr), tipc_cluster(addr), tipc_node(addr));
|
||||
return string;
|
||||
}
|
||||
|
||||
int addr_domain_valid(u32);
|
||||
int addr_node_valid(u32 addr);
|
||||
|
||||
#endif
|
803
net/tipc/bcast.c
Normal file
803
net/tipc/bcast.c
Normal file
|
@ -0,0 +1,803 @@
|
|||
/*
|
||||
* net/tipc/bcast.c: TIPC broadcast code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004, Intel Corporation.
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "msg.h"
|
||||
#include "dbg.h"
|
||||
#include "link.h"
|
||||
#include "net.h"
|
||||
#include "node.h"
|
||||
#include "port.h"
|
||||
#include "addr.h"
|
||||
#include "node_subscr.h"
|
||||
#include "name_distr.h"
|
||||
#include "bearer.h"
|
||||
#include "name_table.h"
|
||||
#include "bcast.h"
|
||||
|
||||
|
||||
#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
|
||||
|
||||
#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
|
||||
|
||||
#define BCLINK_LOG_BUF_SIZE 0
|
||||
|
||||
/**
|
||||
* struct bcbearer_pair - a pair of bearers used by broadcast link
|
||||
* @primary: pointer to primary bearer
|
||||
* @secondary: pointer to secondary bearer
|
||||
*
|
||||
* Bearers must have same priority and same set of reachable destinations
|
||||
* to be paired.
|
||||
*/
|
||||
|
||||
struct bcbearer_pair {
|
||||
struct bearer *primary;
|
||||
struct bearer *secondary;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bcbearer - bearer used by broadcast link
|
||||
* @bearer: (non-standard) broadcast bearer structure
|
||||
* @media: (non-standard) broadcast media structure
|
||||
* @bpairs: array of bearer pairs
|
||||
* @bpairs_temp: array of bearer pairs used during creation of "bpairs"
|
||||
*/
|
||||
|
||||
struct bcbearer {
|
||||
struct bearer bearer;
|
||||
struct media media;
|
||||
struct bcbearer_pair bpairs[MAX_BEARERS];
|
||||
struct bcbearer_pair bpairs_temp[TIPC_NUM_LINK_PRI];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bclink - link used for broadcast messages
|
||||
* @link: (non-standard) broadcast link structure
|
||||
* @node: (non-standard) node structure representing b'cast link's peer node
|
||||
*
|
||||
* Handles sequence numbering, fragmentation, bundling, etc.
|
||||
*/
|
||||
|
||||
struct bclink {
|
||||
struct link link;
|
||||
struct node node;
|
||||
};
|
||||
|
||||
|
||||
static struct bcbearer *bcbearer = NULL;
|
||||
static struct bclink *bclink = NULL;
|
||||
static struct link *bcl = NULL;
|
||||
static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
char bc_link_name[] = "multicast-link";
|
||||
|
||||
|
||||
static inline u32 buf_seqno(struct sk_buff *buf)
|
||||
{
|
||||
return msg_seqno(buf_msg(buf));
|
||||
}
|
||||
|
||||
static inline u32 bcbuf_acks(struct sk_buff *buf)
|
||||
{
|
||||
return (u32)TIPC_SKB_CB(buf)->handle;
|
||||
}
|
||||
|
||||
static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks)
|
||||
{
|
||||
TIPC_SKB_CB(buf)->handle = (void *)acks;
|
||||
}
|
||||
|
||||
static inline void bcbuf_decr_acks(struct sk_buff *buf)
|
||||
{
|
||||
bcbuf_set_acks(buf, bcbuf_acks(buf) - 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* bclink_set_gap - set gap according to contents of current deferred pkt queue
|
||||
*
|
||||
* Called with 'node' locked, bc_lock unlocked
|
||||
*/
|
||||
|
||||
static inline void bclink_set_gap(struct node *n_ptr)
|
||||
{
|
||||
struct sk_buff *buf = n_ptr->bclink.deferred_head;
|
||||
|
||||
n_ptr->bclink.gap_after = n_ptr->bclink.gap_to =
|
||||
mod(n_ptr->bclink.last_in);
|
||||
if (unlikely(buf != NULL))
|
||||
n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_ack_allowed - test if ACK or NACK message can be sent at this moment
|
||||
*
|
||||
* This mechanism endeavours to prevent all nodes in network from trying
|
||||
* to ACK or NACK at the same time.
|
||||
*
|
||||
* Note: TIPC uses a different trigger to distribute ACKs than it does to
|
||||
* distribute NACKs, but tries to use the same spacing (divide by 16).
|
||||
*/
|
||||
|
||||
static inline int bclink_ack_allowed(u32 n)
|
||||
{
|
||||
return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* bclink_retransmit_pkt - retransmit broadcast packets
|
||||
* @after: sequence number of last packet to *not* retransmit
|
||||
* @to: sequence number of last packet to retransmit
|
||||
*
|
||||
* Called with 'node' locked, bc_lock unlocked
|
||||
*/
|
||||
|
||||
static void bclink_retransmit_pkt(u32 after, u32 to)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
buf = bcl->first_out;
|
||||
while (buf && less_eq(buf_seqno(buf), after)) {
|
||||
buf = buf->next;
|
||||
}
|
||||
if (buf != NULL)
|
||||
link_retransmit(bcl, buf, mod(to - after));
|
||||
spin_unlock_bh(&bc_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_acknowledge - handle acknowledgement of broadcast packets
|
||||
* @n_ptr: node that sent acknowledgement info
|
||||
* @acked: broadcast sequence # that has been acknowledged
|
||||
*
|
||||
* Node is locked, bc_lock unlocked.
|
||||
*/
|
||||
|
||||
void bclink_acknowledge(struct node *n_ptr, u32 acked)
|
||||
{
|
||||
struct sk_buff *crs;
|
||||
struct sk_buff *next;
|
||||
unsigned int released = 0;
|
||||
|
||||
if (less_eq(acked, n_ptr->bclink.acked))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
|
||||
/* Skip over packets that node has previously acknowledged */
|
||||
|
||||
crs = bcl->first_out;
|
||||
while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) {
|
||||
crs = crs->next;
|
||||
}
|
||||
|
||||
/* Update packets that node is now acknowledging */
|
||||
|
||||
while (crs && less_eq(buf_seqno(crs), acked)) {
|
||||
next = crs->next;
|
||||
bcbuf_decr_acks(crs);
|
||||
if (bcbuf_acks(crs) == 0) {
|
||||
bcl->first_out = next;
|
||||
bcl->out_queue_size--;
|
||||
buf_discard(crs);
|
||||
released = 1;
|
||||
}
|
||||
crs = next;
|
||||
}
|
||||
n_ptr->bclink.acked = acked;
|
||||
|
||||
/* Try resolving broadcast link congestion, if necessary */
|
||||
|
||||
if (unlikely(bcl->next_out))
|
||||
link_push_queue(bcl);
|
||||
if (unlikely(released && !list_empty(&bcl->waiting_ports)))
|
||||
link_wakeup_ports(bcl, 0);
|
||||
spin_unlock_bh(&bc_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_send_ack - unicast an ACK msg
|
||||
*
|
||||
* net_lock and node lock set
|
||||
*/
|
||||
|
||||
static void bclink_send_ack(struct node *n_ptr)
|
||||
{
|
||||
struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1];
|
||||
|
||||
if (l_ptr != NULL)
|
||||
link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_send_nack- broadcast a NACK msg
|
||||
*
|
||||
* net_lock and node lock set
|
||||
*/
|
||||
|
||||
static void bclink_send_nack(struct node *n_ptr)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct tipc_msg *msg;
|
||||
|
||||
if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to))
|
||||
return;
|
||||
|
||||
buf = buf_acquire(INT_H_SIZE);
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
msg_init(msg, BCAST_PROTOCOL, STATE_MSG,
|
||||
TIPC_OK, INT_H_SIZE, n_ptr->addr);
|
||||
msg_set_mc_netid(msg, tipc_net_id);
|
||||
msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in));
|
||||
msg_set_bcgap_after(msg, n_ptr->bclink.gap_after);
|
||||
msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
|
||||
msg_set_bcast_tag(msg, tipc_own_tag);
|
||||
|
||||
if (bearer_send(&bcbearer->bearer, buf, 0)) {
|
||||
bcl->stats.sent_nacks++;
|
||||
buf_discard(buf);
|
||||
} else {
|
||||
bearer_schedule(bcl->b_ptr, bcl);
|
||||
bcl->proto_msg_queue = buf;
|
||||
bcl->stats.bearer_congs++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure we doesn't send another NACK msg to the node
|
||||
* until 16 more deferred messages arrive from it
|
||||
* (i.e. helps prevent all nodes from NACK'ing at same time)
|
||||
*/
|
||||
|
||||
n_ptr->bclink.nack_sync = tipc_own_tag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_check_gap - send a NACK if a sequence gap exists
|
||||
*
|
||||
* net_lock and node lock set
|
||||
*/
|
||||
|
||||
void bclink_check_gap(struct node *n_ptr, u32 last_sent)
|
||||
{
|
||||
if (!n_ptr->bclink.supported ||
|
||||
less_eq(last_sent, mod(n_ptr->bclink.last_in)))
|
||||
return;
|
||||
|
||||
bclink_set_gap(n_ptr);
|
||||
if (n_ptr->bclink.gap_after == n_ptr->bclink.gap_to)
|
||||
n_ptr->bclink.gap_to = last_sent;
|
||||
bclink_send_nack(n_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_peek_nack - process a NACK msg meant for another node
|
||||
*
|
||||
* Only net_lock set.
|
||||
*/
|
||||
|
||||
void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to)
|
||||
{
|
||||
struct node *n_ptr = node_find(dest);
|
||||
u32 my_after, my_to;
|
||||
|
||||
if (unlikely(!n_ptr || !node_is_up(n_ptr)))
|
||||
return;
|
||||
node_lock(n_ptr);
|
||||
/*
|
||||
* Modify gap to suppress unnecessary NACKs from this node
|
||||
*/
|
||||
my_after = n_ptr->bclink.gap_after;
|
||||
my_to = n_ptr->bclink.gap_to;
|
||||
|
||||
if (less_eq(gap_after, my_after)) {
|
||||
if (less(my_after, gap_to) && less(gap_to, my_to))
|
||||
n_ptr->bclink.gap_after = gap_to;
|
||||
else if (less_eq(my_to, gap_to))
|
||||
n_ptr->bclink.gap_to = n_ptr->bclink.gap_after;
|
||||
} else if (less_eq(gap_after, my_to)) {
|
||||
if (less_eq(my_to, gap_to))
|
||||
n_ptr->bclink.gap_to = gap_after;
|
||||
} else {
|
||||
/*
|
||||
* Expand gap if missing bufs not in deferred queue:
|
||||
*/
|
||||
struct sk_buff *buf = n_ptr->bclink.deferred_head;
|
||||
u32 prev = n_ptr->bclink.gap_to;
|
||||
|
||||
for (; buf; buf = buf->next) {
|
||||
u32 seqno = buf_seqno(buf);
|
||||
|
||||
if (mod(seqno - prev) != 1)
|
||||
buf = NULL;
|
||||
if (seqno == gap_after)
|
||||
break;
|
||||
prev = seqno;
|
||||
}
|
||||
if (buf == NULL)
|
||||
n_ptr->bclink.gap_to = gap_after;
|
||||
}
|
||||
/*
|
||||
* Some nodes may send a complementary NACK now:
|
||||
*/
|
||||
if (bclink_ack_allowed(sender_tag + 1)) {
|
||||
if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) {
|
||||
bclink_send_nack(n_ptr);
|
||||
bclink_set_gap(n_ptr);
|
||||
}
|
||||
}
|
||||
node_unlock(n_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_send_msg - broadcast a packet to all nodes in cluster
|
||||
*/
|
||||
|
||||
int bclink_send_msg(struct sk_buff *buf)
|
||||
{
|
||||
int res;
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
|
||||
res = link_send_buf(bcl, buf);
|
||||
if (unlikely(res == -ELINKCONG))
|
||||
buf_discard(buf);
|
||||
else
|
||||
bcl->stats.sent_info++;
|
||||
|
||||
if (bcl->out_queue_size > bcl->stats.max_queue_sz)
|
||||
bcl->stats.max_queue_sz = bcl->out_queue_size;
|
||||
bcl->stats.queue_sz_counts++;
|
||||
bcl->stats.accu_queue_sz += bcl->out_queue_size;
|
||||
|
||||
spin_unlock_bh(&bc_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* bclink_recv_pkt - receive a broadcast packet, and deliver upwards
|
||||
*
|
||||
* net_lock is read_locked, no other locks set
|
||||
*/
|
||||
|
||||
void bclink_recv_pkt(struct sk_buff *buf)
|
||||
{
|
||||
struct tipc_msg *msg = buf_msg(buf);
|
||||
struct node* node = node_find(msg_prevnode(msg));
|
||||
u32 next_in;
|
||||
u32 seqno;
|
||||
struct sk_buff *deferred;
|
||||
|
||||
msg_dbg(msg, "<BC<<<");
|
||||
|
||||
if (unlikely(!node || !node_is_up(node) || !node->bclink.supported ||
|
||||
(msg_mc_netid(msg) != tipc_net_id))) {
|
||||
buf_discard(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) {
|
||||
msg_dbg(msg, "<BCNACK<<<");
|
||||
if (msg_destnode(msg) == tipc_own_addr) {
|
||||
node_lock(node);
|
||||
bclink_acknowledge(node, msg_bcast_ack(msg));
|
||||
node_unlock(node);
|
||||
bcl->stats.recv_nacks++;
|
||||
bclink_retransmit_pkt(msg_bcgap_after(msg),
|
||||
msg_bcgap_to(msg));
|
||||
} else {
|
||||
bclink_peek_nack(msg_destnode(msg),
|
||||
msg_bcast_tag(msg),
|
||||
msg_bcgap_after(msg),
|
||||
msg_bcgap_to(msg));
|
||||
}
|
||||
buf_discard(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
node_lock(node);
|
||||
receive:
|
||||
deferred = node->bclink.deferred_head;
|
||||
next_in = mod(node->bclink.last_in + 1);
|
||||
seqno = msg_seqno(msg);
|
||||
|
||||
if (likely(seqno == next_in)) {
|
||||
bcl->stats.recv_info++;
|
||||
node->bclink.last_in++;
|
||||
bclink_set_gap(node);
|
||||
if (unlikely(bclink_ack_allowed(seqno))) {
|
||||
bclink_send_ack(node);
|
||||
bcl->stats.sent_acks++;
|
||||
}
|
||||
if (likely(msg_isdata(msg))) {
|
||||
node_unlock(node);
|
||||
port_recv_mcast(buf, NULL);
|
||||
} else if (msg_user(msg) == MSG_BUNDLER) {
|
||||
bcl->stats.recv_bundles++;
|
||||
bcl->stats.recv_bundled += msg_msgcnt(msg);
|
||||
node_unlock(node);
|
||||
link_recv_bundle(buf);
|
||||
} else if (msg_user(msg) == MSG_FRAGMENTER) {
|
||||
bcl->stats.recv_fragments++;
|
||||
if (link_recv_fragment(&node->bclink.defragm,
|
||||
&buf, &msg))
|
||||
bcl->stats.recv_fragmented++;
|
||||
node_unlock(node);
|
||||
net_route_msg(buf);
|
||||
} else {
|
||||
node_unlock(node);
|
||||
net_route_msg(buf);
|
||||
}
|
||||
if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) {
|
||||
node_lock(node);
|
||||
buf = deferred;
|
||||
msg = buf_msg(buf);
|
||||
node->bclink.deferred_head = deferred->next;
|
||||
goto receive;
|
||||
}
|
||||
return;
|
||||
} else if (less(next_in, seqno)) {
|
||||
u32 gap_after = node->bclink.gap_after;
|
||||
u32 gap_to = node->bclink.gap_to;
|
||||
|
||||
if (link_defer_pkt(&node->bclink.deferred_head,
|
||||
&node->bclink.deferred_tail,
|
||||
buf)) {
|
||||
node->bclink.nack_sync++;
|
||||
bcl->stats.deferred_recv++;
|
||||
if (seqno == mod(gap_after + 1))
|
||||
node->bclink.gap_after = seqno;
|
||||
else if (less(gap_after, seqno) && less(seqno, gap_to))
|
||||
node->bclink.gap_to = seqno;
|
||||
}
|
||||
if (bclink_ack_allowed(node->bclink.nack_sync)) {
|
||||
if (gap_to != gap_after)
|
||||
bclink_send_nack(node);
|
||||
bclink_set_gap(node);
|
||||
}
|
||||
} else {
|
||||
bcl->stats.duplicates++;
|
||||
buf_discard(buf);
|
||||
}
|
||||
node_unlock(node);
|
||||
}
|
||||
|
||||
u32 bclink_get_last_sent(void)
|
||||
{
|
||||
u32 last_sent = mod(bcl->next_out_no - 1);
|
||||
|
||||
if (bcl->next_out)
|
||||
last_sent = mod(buf_seqno(bcl->next_out) - 1);
|
||||
return last_sent;
|
||||
}
|
||||
|
||||
u32 bclink_acks_missing(struct node *n_ptr)
|
||||
{
|
||||
return (n_ptr->bclink.supported &&
|
||||
(bclink_get_last_sent() != n_ptr->bclink.acked));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* bcbearer_send - send a packet through the broadcast pseudo-bearer
|
||||
*
|
||||
* Send through as many bearers as necessary to reach all nodes
|
||||
* that support TIPC multicasting.
|
||||
*
|
||||
* Returns 0 if packet sent successfully, non-zero if not
|
||||
*/
|
||||
|
||||
int bcbearer_send(struct sk_buff *buf,
|
||||
struct tipc_bearer *unused1,
|
||||
struct tipc_media_addr *unused2)
|
||||
{
|
||||
static int send_count = 0;
|
||||
|
||||
struct node_map remains;
|
||||
struct node_map remains_new;
|
||||
int bp_index;
|
||||
int swap_time;
|
||||
|
||||
/* Prepare buffer for broadcasting (if first time trying to send it) */
|
||||
|
||||
if (likely(!msg_non_seq(buf_msg(buf)))) {
|
||||
struct tipc_msg *msg;
|
||||
|
||||
assert(cluster_bcast_nodes.count != 0);
|
||||
bcbuf_set_acks(buf, cluster_bcast_nodes.count);
|
||||
msg = buf_msg(buf);
|
||||
msg_set_non_seq(msg);
|
||||
msg_set_mc_netid(msg, tipc_net_id);
|
||||
}
|
||||
|
||||
/* Determine if bearer pairs should be swapped following this attempt */
|
||||
|
||||
if ((swap_time = (++send_count >= 10)))
|
||||
send_count = 0;
|
||||
|
||||
/* Send buffer over bearers until all targets reached */
|
||||
|
||||
remains = cluster_bcast_nodes;
|
||||
|
||||
for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
|
||||
struct bearer *p = bcbearer->bpairs[bp_index].primary;
|
||||
struct bearer *s = bcbearer->bpairs[bp_index].secondary;
|
||||
|
||||
if (!p)
|
||||
break; /* no more bearers to try */
|
||||
|
||||
nmap_diff(&remains, &p->nodes, &remains_new);
|
||||
if (remains_new.count == remains.count)
|
||||
continue; /* bearer pair doesn't add anything */
|
||||
|
||||
if (!p->publ.blocked &&
|
||||
!p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) {
|
||||
if (swap_time && s && !s->publ.blocked)
|
||||
goto swap;
|
||||
else
|
||||
goto update;
|
||||
}
|
||||
|
||||
if (!s || s->publ.blocked ||
|
||||
s->media->send_msg(buf, &s->publ, &s->media->bcast_addr))
|
||||
continue; /* unable to send using bearer pair */
|
||||
swap:
|
||||
bcbearer->bpairs[bp_index].primary = s;
|
||||
bcbearer->bpairs[bp_index].secondary = p;
|
||||
update:
|
||||
if (remains_new.count == 0)
|
||||
return TIPC_OK;
|
||||
|
||||
remains = remains_new;
|
||||
}
|
||||
|
||||
/* Unable to reach all targets */
|
||||
|
||||
bcbearer->bearer.publ.blocked = 1;
|
||||
bcl->stats.bearer_congs++;
|
||||
return ~TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bcbearer_sort - create sets of bearer pairs used by broadcast bearer
|
||||
*/
|
||||
|
||||
void bcbearer_sort(void)
|
||||
{
|
||||
struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp;
|
||||
struct bcbearer_pair *bp_curr;
|
||||
int b_index;
|
||||
int pri;
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
|
||||
/* Group bearers by priority (can assume max of two per priority) */
|
||||
|
||||
memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
|
||||
|
||||
for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
|
||||
struct bearer *b = &bearers[b_index];
|
||||
|
||||
if (!b->active || !b->nodes.count)
|
||||
continue;
|
||||
|
||||
if (!bp_temp[b->priority].primary)
|
||||
bp_temp[b->priority].primary = b;
|
||||
else
|
||||
bp_temp[b->priority].secondary = b;
|
||||
}
|
||||
|
||||
/* Create array of bearer pairs for broadcasting */
|
||||
|
||||
bp_curr = bcbearer->bpairs;
|
||||
memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs));
|
||||
|
||||
for (pri = (TIPC_NUM_LINK_PRI - 1); pri >= 0; pri--) {
|
||||
|
||||
if (!bp_temp[pri].primary)
|
||||
continue;
|
||||
|
||||
bp_curr->primary = bp_temp[pri].primary;
|
||||
|
||||
if (bp_temp[pri].secondary) {
|
||||
if (nmap_equal(&bp_temp[pri].primary->nodes,
|
||||
&bp_temp[pri].secondary->nodes)) {
|
||||
bp_curr->secondary = bp_temp[pri].secondary;
|
||||
} else {
|
||||
bp_curr++;
|
||||
bp_curr->primary = bp_temp[pri].secondary;
|
||||
}
|
||||
}
|
||||
|
||||
bp_curr++;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&bc_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* bcbearer_push - resolve bearer congestion
|
||||
*
|
||||
* Forces bclink to push out any unsent packets, until all packets are gone
|
||||
* or congestion reoccurs.
|
||||
* No locks set when function called
|
||||
*/
|
||||
|
||||
void bcbearer_push(void)
|
||||
{
|
||||
struct bearer *b_ptr;
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
b_ptr = &bcbearer->bearer;
|
||||
if (b_ptr->publ.blocked) {
|
||||
b_ptr->publ.blocked = 0;
|
||||
bearer_lock_push(b_ptr);
|
||||
}
|
||||
spin_unlock_bh(&bc_lock);
|
||||
}
|
||||
|
||||
|
||||
int bclink_stats(char *buf, const u32 buf_size)
|
||||
{
|
||||
struct print_buf pb;
|
||||
|
||||
if (!bcl)
|
||||
return 0;
|
||||
|
||||
printbuf_init(&pb, buf, buf_size);
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
|
||||
tipc_printf(&pb, "Link <%s>\n"
|
||||
" Window:%u packets\n",
|
||||
bcl->name, bcl->queue_limit[0]);
|
||||
tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
|
||||
bcl->stats.recv_info,
|
||||
bcl->stats.recv_fragments,
|
||||
bcl->stats.recv_fragmented,
|
||||
bcl->stats.recv_bundles,
|
||||
bcl->stats.recv_bundled);
|
||||
tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
|
||||
bcl->stats.sent_info,
|
||||
bcl->stats.sent_fragments,
|
||||
bcl->stats.sent_fragmented,
|
||||
bcl->stats.sent_bundles,
|
||||
bcl->stats.sent_bundled);
|
||||
tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n",
|
||||
bcl->stats.recv_nacks,
|
||||
bcl->stats.deferred_recv,
|
||||
bcl->stats.duplicates);
|
||||
tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n",
|
||||
bcl->stats.sent_nacks,
|
||||
bcl->stats.sent_acks,
|
||||
bcl->stats.retransmitted);
|
||||
tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
|
||||
bcl->stats.bearer_congs,
|
||||
bcl->stats.link_congs,
|
||||
bcl->stats.max_queue_sz,
|
||||
bcl->stats.queue_sz_counts
|
||||
? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts)
|
||||
: 0);
|
||||
|
||||
spin_unlock_bh(&bc_lock);
|
||||
return printbuf_validate(&pb);
|
||||
}
|
||||
|
||||
int bclink_reset_stats(void)
|
||||
{
|
||||
if (!bcl)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
memset(&bcl->stats, 0, sizeof(bcl->stats));
|
||||
spin_unlock_bh(&bc_lock);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
int bclink_set_queue_limits(u32 limit)
|
||||
{
|
||||
if (!bcl)
|
||||
return -ENOPROTOOPT;
|
||||
if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_bh(&bc_lock);
|
||||
link_set_queue_limits(bcl, limit);
|
||||
spin_unlock_bh(&bc_lock);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
int bclink_init(void)
|
||||
{
|
||||
bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC);
|
||||
bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
|
||||
if (!bcbearer || !bclink) {
|
||||
nomem:
|
||||
warn("Memory squeeze; Failed to create multicast link\n");
|
||||
kfree(bcbearer);
|
||||
bcbearer = NULL;
|
||||
kfree(bclink);
|
||||
bclink = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(bcbearer, 0, sizeof(struct bcbearer));
|
||||
INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
|
||||
bcbearer->bearer.media = &bcbearer->media;
|
||||
bcbearer->media.send_msg = bcbearer_send;
|
||||
sprintf(bcbearer->media.name, "tipc-multicast");
|
||||
|
||||
bcl = &bclink->link;
|
||||
memset(bclink, 0, sizeof(struct bclink));
|
||||
INIT_LIST_HEAD(&bcl->waiting_ports);
|
||||
bcl->next_out_no = 1;
|
||||
bclink->node.lock = SPIN_LOCK_UNLOCKED;
|
||||
bcl->owner = &bclink->node;
|
||||
bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
|
||||
link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
|
||||
bcl->b_ptr = &bcbearer->bearer;
|
||||
bcl->state = WORKING_WORKING;
|
||||
sprintf(bcl->name, bc_link_name);
|
||||
|
||||
if (BCLINK_LOG_BUF_SIZE) {
|
||||
char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC);
|
||||
|
||||
if (!pb)
|
||||
goto nomem;
|
||||
printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE);
|
||||
}
|
||||
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
void bclink_stop(void)
|
||||
{
|
||||
spin_lock_bh(&bc_lock);
|
||||
if (bcbearer) {
|
||||
link_stop(bcl);
|
||||
if (BCLINK_LOG_BUF_SIZE)
|
||||
kfree(bcl->print_buf.buf);
|
||||
bcl = NULL;
|
||||
kfree(bclink);
|
||||
bclink = NULL;
|
||||
kfree(bcbearer);
|
||||
bcbearer = NULL;
|
||||
}
|
||||
spin_unlock_bh(&bc_lock);
|
||||
}
|
||||
|
220
net/tipc/bcast.h
Normal file
220
net/tipc/bcast.h
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* net/tipc/bcast.h: Include file for TIPC broadcast code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_BCAST_H
|
||||
#define _TIPC_BCAST_H
|
||||
|
||||
#define MAX_NODES 4096
|
||||
#define WSIZE 32
|
||||
|
||||
/**
|
||||
* struct node_map - set of node identifiers
|
||||
* @count: # of nodes in set
|
||||
* @map: bitmap of node identifiers that are in the set
|
||||
*/
|
||||
|
||||
struct node_map {
|
||||
u32 count;
|
||||
u32 map[MAX_NODES / WSIZE];
|
||||
};
|
||||
|
||||
|
||||
#define PLSIZE 32
|
||||
|
||||
/**
|
||||
* struct port_list - set of node local destination ports
|
||||
* @count: # of ports in set (only valid for first entry in list)
|
||||
* @next: pointer to next entry in list
|
||||
* @ports: array of port references
|
||||
*/
|
||||
|
||||
struct port_list {
|
||||
int count;
|
||||
struct port_list *next;
|
||||
u32 ports[PLSIZE];
|
||||
};
|
||||
|
||||
|
||||
struct node;
|
||||
|
||||
extern char bc_link_name[];
|
||||
|
||||
|
||||
/**
|
||||
* nmap_get - determine if node exists in a node map
|
||||
*/
|
||||
|
||||
static inline int nmap_get(struct node_map *nm_ptr, u32 node)
|
||||
{
|
||||
int n = tipc_node(node);
|
||||
int w = n / WSIZE;
|
||||
int b = n % WSIZE;
|
||||
|
||||
return nm_ptr->map[w] & (1 << b);
|
||||
}
|
||||
|
||||
/**
|
||||
* nmap_add - add a node to a node map
|
||||
*/
|
||||
|
||||
static inline void nmap_add(struct node_map *nm_ptr, u32 node)
|
||||
{
|
||||
int n = tipc_node(node);
|
||||
int w = n / WSIZE;
|
||||
u32 mask = (1 << (n % WSIZE));
|
||||
|
||||
if ((nm_ptr->map[w] & mask) == 0) {
|
||||
nm_ptr->count++;
|
||||
nm_ptr->map[w] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nmap_remove - remove a node from a node map
|
||||
*/
|
||||
|
||||
static inline void nmap_remove(struct node_map *nm_ptr, u32 node)
|
||||
{
|
||||
int n = tipc_node(node);
|
||||
int w = n / WSIZE;
|
||||
u32 mask = (1 << (n % WSIZE));
|
||||
|
||||
if ((nm_ptr->map[w] & mask) != 0) {
|
||||
nm_ptr->map[w] &= ~mask;
|
||||
nm_ptr->count--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nmap_equal - test for equality of node maps
|
||||
*/
|
||||
|
||||
static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b)
|
||||
{
|
||||
return !memcmp(nm_a, nm_b, sizeof(*nm_a));
|
||||
}
|
||||
|
||||
/**
|
||||
* nmap_diff - find differences between node maps
|
||||
* @nm_a: input node map A
|
||||
* @nm_b: input node map B
|
||||
* @nm_diff: output node map A-B (i.e. nodes of A that are not in B)
|
||||
*/
|
||||
|
||||
static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b,
|
||||
struct node_map *nm_diff)
|
||||
{
|
||||
int stop = sizeof(nm_a->map) / sizeof(u32);
|
||||
int w;
|
||||
int b;
|
||||
u32 map;
|
||||
|
||||
memset(nm_diff, 0, sizeof(*nm_diff));
|
||||
for (w = 0; w < stop; w++) {
|
||||
map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]);
|
||||
nm_diff->map[w] = map;
|
||||
if (map != 0) {
|
||||
for (b = 0 ; b < WSIZE; b++) {
|
||||
if (map & (1 << b))
|
||||
nm_diff->count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* port_list_add - add a port to a port list, ensuring no duplicates
|
||||
*/
|
||||
|
||||
static inline void port_list_add(struct port_list *pl_ptr, u32 port)
|
||||
{
|
||||
struct port_list *item = pl_ptr;
|
||||
int i;
|
||||
int item_sz = PLSIZE;
|
||||
int cnt = pl_ptr->count;
|
||||
|
||||
for (; ; cnt -= item_sz, item = item->next) {
|
||||
if (cnt < PLSIZE)
|
||||
item_sz = cnt;
|
||||
for (i = 0; i < item_sz; i++)
|
||||
if (item->ports[i] == port)
|
||||
return;
|
||||
if (i < PLSIZE) {
|
||||
item->ports[i] = port;
|
||||
pl_ptr->count++;
|
||||
return;
|
||||
}
|
||||
if (!item->next) {
|
||||
item->next = kmalloc(sizeof(*item), GFP_ATOMIC);
|
||||
if (!item->next) {
|
||||
warn("Memory squeeze: multicast destination port list is incomplete\n");
|
||||
return;
|
||||
}
|
||||
item->next->next = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* port_list_free - free dynamically created entries in port_list chain
|
||||
*
|
||||
* Note: First item is on stack, so it doesn't need to be released
|
||||
*/
|
||||
|
||||
static inline void port_list_free(struct port_list *pl_ptr)
|
||||
{
|
||||
struct port_list *item;
|
||||
struct port_list *next;
|
||||
|
||||
for (item = pl_ptr->next; item; item = next) {
|
||||
next = item->next;
|
||||
kfree(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int bclink_init(void);
|
||||
void bclink_stop(void);
|
||||
void bclink_acknowledge(struct node *n_ptr, u32 acked);
|
||||
int bclink_send_msg(struct sk_buff *buf);
|
||||
void bclink_recv_pkt(struct sk_buff *buf);
|
||||
u32 bclink_get_last_sent(void);
|
||||
u32 bclink_acks_missing(struct node *n_ptr);
|
||||
void bclink_check_gap(struct node *n_ptr, u32 seqno);
|
||||
int bclink_stats(char *stats_buf, const u32 buf_size);
|
||||
int bclink_reset_stats(void);
|
||||
int bclink_set_queue_limits(u32 limit);
|
||||
void bcbearer_sort(void);
|
||||
void bcbearer_push(void);
|
||||
|
||||
#endif
|
689
net/tipc/bearer.c
Normal file
689
net/tipc/bearer.c
Normal file
|
@ -0,0 +1,689 @@
|
|||
/*
|
||||
* net/tipc/bearer.c: TIPC bearer code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "config.h"
|
||||
#include "dbg.h"
|
||||
#include "bearer.h"
|
||||
#include "link.h"
|
||||
#include "port.h"
|
||||
#include "discover.h"
|
||||
#include "bcast.h"
|
||||
|
||||
#define MAX_ADDR_STR 32
|
||||
|
||||
static struct media *media_list = 0;
|
||||
static u32 media_count = 0;
|
||||
|
||||
struct bearer *bearers = 0;
|
||||
|
||||
/**
|
||||
* media_name_valid - validate media name
|
||||
*
|
||||
* Returns 1 if media name is valid, otherwise 0.
|
||||
*/
|
||||
|
||||
static int media_name_valid(const char *name)
|
||||
{
|
||||
u32 len;
|
||||
|
||||
len = strlen(name);
|
||||
if ((len + 1) > TIPC_MAX_MEDIA_NAME)
|
||||
return 0;
|
||||
return (strspn(name, tipc_alphabet) == len);
|
||||
}
|
||||
|
||||
/**
|
||||
* media_find - locates specified media object by name
|
||||
*/
|
||||
|
||||
static struct media *media_find(const char *name)
|
||||
{
|
||||
struct media *m_ptr;
|
||||
u32 i;
|
||||
|
||||
for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
|
||||
if (!strcmp(m_ptr->name, name))
|
||||
return m_ptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_register_media - register a media type
|
||||
*
|
||||
* Bearers for this media type must be activated separately at a later stage.
|
||||
*/
|
||||
|
||||
int tipc_register_media(u32 media_type,
|
||||
char *name,
|
||||
int (*enable)(struct tipc_bearer *),
|
||||
void (*disable)(struct tipc_bearer *),
|
||||
int (*send_msg)(struct sk_buff *,
|
||||
struct tipc_bearer *,
|
||||
struct tipc_media_addr *),
|
||||
char *(*addr2str)(struct tipc_media_addr *a,
|
||||
char *str_buf, int str_size),
|
||||
struct tipc_media_addr *bcast_addr,
|
||||
const u32 bearer_priority,
|
||||
const u32 link_tolerance, /* [ms] */
|
||||
const u32 send_window_limit)
|
||||
{
|
||||
struct media *m_ptr;
|
||||
u32 media_id;
|
||||
u32 i;
|
||||
int res = -EINVAL;
|
||||
|
||||
write_lock_bh(&net_lock);
|
||||
if (!media_list)
|
||||
goto exit;
|
||||
|
||||
if (!media_name_valid(name)) {
|
||||
warn("Media registration error: illegal name <%s>\n", name);
|
||||
goto exit;
|
||||
}
|
||||
if (!bcast_addr) {
|
||||
warn("Media registration error: no broadcast address supplied\n");
|
||||
goto exit;
|
||||
}
|
||||
if (bearer_priority >= TIPC_NUM_LINK_PRI) {
|
||||
warn("Media registration error: priority %u\n", bearer_priority);
|
||||
goto exit;
|
||||
}
|
||||
if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
|
||||
(link_tolerance > TIPC_MAX_LINK_TOL)) {
|
||||
warn("Media registration error: tolerance %u\n", link_tolerance);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
media_id = media_count++;
|
||||
if (media_id >= MAX_MEDIA) {
|
||||
warn("Attempt to register more than %u media\n", MAX_MEDIA);
|
||||
media_count--;
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < media_id; i++) {
|
||||
if (media_list[i].type_id == media_type) {
|
||||
warn("Attempt to register second media with type %u\n",
|
||||
media_type);
|
||||
media_count--;
|
||||
goto exit;
|
||||
}
|
||||
if (!strcmp(name, media_list[i].name)) {
|
||||
warn("Attempt to re-register media name <%s>\n", name);
|
||||
media_count--;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
m_ptr = &media_list[media_id];
|
||||
m_ptr->type_id = media_type;
|
||||
m_ptr->send_msg = send_msg;
|
||||
m_ptr->enable_bearer = enable;
|
||||
m_ptr->disable_bearer = disable;
|
||||
m_ptr->addr2str = addr2str;
|
||||
memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
|
||||
m_ptr->bcast = 1;
|
||||
strcpy(m_ptr->name, name);
|
||||
m_ptr->priority = bearer_priority;
|
||||
m_ptr->tolerance = link_tolerance;
|
||||
m_ptr->window = send_window_limit;
|
||||
dbg("Media <%s> registered\n", name);
|
||||
res = 0;
|
||||
exit:
|
||||
write_unlock_bh(&net_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* media_addr_printf - record media address in print buffer
|
||||
*/
|
||||
|
||||
void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
|
||||
{
|
||||
struct media *m_ptr;
|
||||
u32 media_type;
|
||||
u32 i;
|
||||
|
||||
media_type = ntohl(a->type);
|
||||
for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
|
||||
if (m_ptr->type_id == media_type)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((i < media_count) && (m_ptr->addr2str != NULL)) {
|
||||
char addr_str[MAX_ADDR_STR];
|
||||
|
||||
tipc_printf(pb, "%s(%s) ", m_ptr->name,
|
||||
m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
|
||||
} else {
|
||||
unchar *addr = (unchar *)&a->dev_addr;
|
||||
|
||||
tipc_printf(pb, "UNKNOWN(%u):", media_type);
|
||||
for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
|
||||
tipc_printf(pb, "%02x ", addr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* media_get_names - record names of registered media in buffer
|
||||
*/
|
||||
|
||||
struct sk_buff *media_get_names(void)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct media *m_ptr;
|
||||
int i;
|
||||
|
||||
buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
read_lock_bh(&net_lock);
|
||||
for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
|
||||
cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name,
|
||||
strlen(m_ptr->name) + 1);
|
||||
}
|
||||
read_unlock_bh(&net_lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* bearer_name_validate - validate & (optionally) deconstruct bearer name
|
||||
* @name - ptr to bearer name string
|
||||
* @name_parts - ptr to area for bearer name components (or NULL if not needed)
|
||||
*
|
||||
* Returns 1 if bearer name is valid, otherwise 0.
|
||||
*/
|
||||
|
||||
static int bearer_name_validate(const char *name,
|
||||
struct bearer_name *name_parts)
|
||||
{
|
||||
char name_copy[TIPC_MAX_BEARER_NAME];
|
||||
char *media_name;
|
||||
char *if_name;
|
||||
u32 media_len;
|
||||
u32 if_len;
|
||||
|
||||
/* copy bearer name & ensure length is OK */
|
||||
|
||||
name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
|
||||
/* need above in case non-Posix strncpy() doesn't pad with nulls */
|
||||
strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
|
||||
if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* ensure all component parts of bearer name are present */
|
||||
|
||||
media_name = name_copy;
|
||||
if ((if_name = strchr(media_name, ':')) == NULL)
|
||||
return 0;
|
||||
*(if_name++) = 0;
|
||||
media_len = if_name - media_name;
|
||||
if_len = strlen(if_name) + 1;
|
||||
|
||||
/* validate component parts of bearer name */
|
||||
|
||||
if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
|
||||
(if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) ||
|
||||
(strspn(media_name, tipc_alphabet) != (media_len - 1)) ||
|
||||
(strspn(if_name, tipc_alphabet) != (if_len - 1)))
|
||||
return 0;
|
||||
|
||||
/* return bearer name components, if necessary */
|
||||
|
||||
if (name_parts) {
|
||||
strcpy(name_parts->media_name, media_name);
|
||||
strcpy(name_parts->if_name, if_name);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* bearer_find - locates bearer object with matching bearer name
|
||||
*/
|
||||
|
||||
static struct bearer *bearer_find(const char *name)
|
||||
{
|
||||
struct bearer *b_ptr;
|
||||
u32 i;
|
||||
|
||||
for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
|
||||
if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
|
||||
return b_ptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bearer_find - locates bearer object with matching interface name
|
||||
*/
|
||||
|
||||
struct bearer *bearer_find_interface(const char *if_name)
|
||||
{
|
||||
struct bearer *b_ptr;
|
||||
char *b_if_name;
|
||||
u32 i;
|
||||
|
||||
for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
|
||||
if (!b_ptr->active)
|
||||
continue;
|
||||
b_if_name = strchr(b_ptr->publ.name, ':') + 1;
|
||||
if (!strcmp(b_if_name, if_name))
|
||||
return b_ptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bearer_get_names - record names of bearers in buffer
|
||||
*/
|
||||
|
||||
struct sk_buff *bearer_get_names(void)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct media *m_ptr;
|
||||
struct bearer *b_ptr;
|
||||
int i, j;
|
||||
|
||||
buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
read_lock_bh(&net_lock);
|
||||
for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
|
||||
for (j = 0; j < MAX_BEARERS; j++) {
|
||||
b_ptr = &bearers[j];
|
||||
if (b_ptr->active && (b_ptr->media == m_ptr)) {
|
||||
cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
|
||||
b_ptr->publ.name,
|
||||
strlen(b_ptr->publ.name) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
read_unlock_bh(&net_lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void bearer_add_dest(struct bearer *b_ptr, u32 dest)
|
||||
{
|
||||
nmap_add(&b_ptr->nodes, dest);
|
||||
disc_update_link_req(b_ptr->link_req);
|
||||
bcbearer_sort();
|
||||
}
|
||||
|
||||
void bearer_remove_dest(struct bearer *b_ptr, u32 dest)
|
||||
{
|
||||
nmap_remove(&b_ptr->nodes, dest);
|
||||
disc_update_link_req(b_ptr->link_req);
|
||||
bcbearer_sort();
|
||||
}
|
||||
|
||||
/*
|
||||
* bearer_push(): Resolve bearer congestion. Force the waiting
|
||||
* links to push out their unsent packets, one packet per link
|
||||
* per iteration, until all packets are gone or congestion reoccurs.
|
||||
* 'net_lock' is read_locked when this function is called
|
||||
* bearer.lock must be taken before calling
|
||||
* Returns binary true(1) ore false(0)
|
||||
*/
|
||||
static int bearer_push(struct bearer *b_ptr)
|
||||
{
|
||||
u32 res = TIPC_OK;
|
||||
struct link *ln, *tln;
|
||||
|
||||
if (b_ptr->publ.blocked)
|
||||
return 0;
|
||||
|
||||
while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
|
||||
list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
|
||||
res = link_push_packet(ln);
|
||||
if (res == PUSH_FAILED)
|
||||
break;
|
||||
if (res == PUSH_FINISHED)
|
||||
list_move_tail(&ln->link_list, &b_ptr->links);
|
||||
}
|
||||
}
|
||||
return list_empty(&b_ptr->cong_links);
|
||||
}
|
||||
|
||||
void bearer_lock_push(struct bearer *b_ptr)
|
||||
{
|
||||
int res;
|
||||
|
||||
spin_lock_bh(&b_ptr->publ.lock);
|
||||
res = bearer_push(b_ptr);
|
||||
spin_unlock_bh(&b_ptr->publ.lock);
|
||||
if (res)
|
||||
bcbearer_push();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt enabling new requests after bearer congestion or blocking:
|
||||
* See bearer_send().
|
||||
*/
|
||||
void tipc_continue(struct tipc_bearer *tb_ptr)
|
||||
{
|
||||
struct bearer *b_ptr = (struct bearer *)tb_ptr;
|
||||
|
||||
spin_lock_bh(&b_ptr->publ.lock);
|
||||
b_ptr->continue_count++;
|
||||
if (!list_empty(&b_ptr->cong_links))
|
||||
k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr);
|
||||
b_ptr->publ.blocked = 0;
|
||||
spin_unlock_bh(&b_ptr->publ.lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Schedule link for sending of messages after the bearer
|
||||
* has been deblocked by 'continue()'. This method is called
|
||||
* when somebody tries to send a message via this link while
|
||||
* the bearer is congested. 'net_lock' is in read_lock here
|
||||
* bearer.lock is busy
|
||||
*/
|
||||
|
||||
static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
|
||||
{
|
||||
list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
|
||||
}
|
||||
|
||||
/*
|
||||
* Schedule link for sending of messages after the bearer
|
||||
* has been deblocked by 'continue()'. This method is called
|
||||
* when somebody tries to send a message via this link while
|
||||
* the bearer is congested. 'net_lock' is in read_lock here,
|
||||
* bearer.lock is free
|
||||
*/
|
||||
|
||||
void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
|
||||
{
|
||||
spin_lock_bh(&b_ptr->publ.lock);
|
||||
bearer_schedule_unlocked(b_ptr, l_ptr);
|
||||
spin_unlock_bh(&b_ptr->publ.lock);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bearer_resolve_congestion(): Check if there is bearer congestion,
|
||||
* and if there is, try to resolve it before returning.
|
||||
* 'net_lock' is read_locked when this function is called
|
||||
*/
|
||||
int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
|
||||
{
|
||||
int res = 1;
|
||||
|
||||
if (list_empty(&b_ptr->cong_links))
|
||||
return 1;
|
||||
spin_lock_bh(&b_ptr->publ.lock);
|
||||
if (!bearer_push(b_ptr)) {
|
||||
bearer_schedule_unlocked(b_ptr, l_ptr);
|
||||
res = 0;
|
||||
}
|
||||
spin_unlock_bh(&b_ptr->publ.lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* tipc_enable_bearer - enable bearer with the given name
|
||||
*/
|
||||
|
||||
int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
|
||||
{
|
||||
struct bearer *b_ptr;
|
||||
struct media *m_ptr;
|
||||
struct bearer_name b_name;
|
||||
char addr_string[16];
|
||||
u32 bearer_id;
|
||||
u32 with_this_prio;
|
||||
u32 i;
|
||||
int res = -EINVAL;
|
||||
|
||||
if (tipc_mode != TIPC_NET_MODE)
|
||||
return -ENOPROTOOPT;
|
||||
if (!bearer_name_validate(name, &b_name) ||
|
||||
!addr_domain_valid(bcast_scope) ||
|
||||
!in_scope(bcast_scope, tipc_own_addr) ||
|
||||
(priority > TIPC_NUM_LINK_PRI))
|
||||
return -EINVAL;
|
||||
|
||||
write_lock_bh(&net_lock);
|
||||
if (!bearers)
|
||||
goto failed;
|
||||
|
||||
m_ptr = media_find(b_name.media_name);
|
||||
if (!m_ptr) {
|
||||
warn("No media <%s>\n", b_name.media_name);
|
||||
goto failed;
|
||||
}
|
||||
if (priority == TIPC_NUM_LINK_PRI)
|
||||
priority = m_ptr->priority;
|
||||
|
||||
restart:
|
||||
bearer_id = MAX_BEARERS;
|
||||
with_this_prio = 1;
|
||||
for (i = MAX_BEARERS; i-- != 0; ) {
|
||||
if (!bearers[i].active) {
|
||||
bearer_id = i;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, bearers[i].publ.name)) {
|
||||
warn("Bearer <%s> already enabled\n", name);
|
||||
goto failed;
|
||||
}
|
||||
if ((bearers[i].priority == priority) &&
|
||||
(++with_this_prio > 2)) {
|
||||
if (priority-- == 0) {
|
||||
warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
|
||||
name, priority + 1, priority);
|
||||
goto failed;
|
||||
}
|
||||
warn("Third bearer <%s> with priority %u, lowering to %u\n",
|
||||
name, priority + 1, priority);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
if (bearer_id >= MAX_BEARERS) {
|
||||
warn("Attempt to enable more than %d bearers\n", MAX_BEARERS);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
b_ptr = &bearers[bearer_id];
|
||||
memset(b_ptr, 0, sizeof(struct bearer));
|
||||
|
||||
strcpy(b_ptr->publ.name, name);
|
||||
res = m_ptr->enable_bearer(&b_ptr->publ);
|
||||
if (res) {
|
||||
warn("Failed to enable bearer <%s>\n", name);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
b_ptr->identity = bearer_id;
|
||||
b_ptr->media = m_ptr;
|
||||
b_ptr->net_plane = bearer_id + 'A';
|
||||
b_ptr->active = 1;
|
||||
b_ptr->detect_scope = bcast_scope;
|
||||
b_ptr->priority = priority;
|
||||
INIT_LIST_HEAD(&b_ptr->cong_links);
|
||||
INIT_LIST_HEAD(&b_ptr->links);
|
||||
if (m_ptr->bcast) {
|
||||
b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
|
||||
bcast_scope, 2);
|
||||
}
|
||||
b_ptr->publ.lock = SPIN_LOCK_UNLOCKED;
|
||||
write_unlock_bh(&net_lock);
|
||||
info("Enabled bearer <%s>, discovery domain %s\n",
|
||||
name, addr_string_fill(addr_string, bcast_scope));
|
||||
return 0;
|
||||
failed:
|
||||
write_unlock_bh(&net_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_block_bearer(): Block the bearer with the given name,
|
||||
* and reset all its links
|
||||
*/
|
||||
|
||||
int tipc_block_bearer(const char *name)
|
||||
{
|
||||
struct bearer *b_ptr = 0;
|
||||
struct link *l_ptr;
|
||||
struct link *temp_l_ptr;
|
||||
|
||||
if (tipc_mode != TIPC_NET_MODE)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
read_lock_bh(&net_lock);
|
||||
b_ptr = bearer_find(name);
|
||||
if (!b_ptr) {
|
||||
warn("Attempt to block unknown bearer <%s>\n", name);
|
||||
read_unlock_bh(&net_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_bh(&b_ptr->publ.lock);
|
||||
b_ptr->publ.blocked = 1;
|
||||
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
|
||||
struct node *n_ptr = l_ptr->owner;
|
||||
|
||||
spin_lock_bh(&n_ptr->lock);
|
||||
link_reset(l_ptr);
|
||||
spin_unlock_bh(&n_ptr->lock);
|
||||
}
|
||||
spin_unlock_bh(&b_ptr->publ.lock);
|
||||
read_unlock_bh(&net_lock);
|
||||
info("Blocked bearer <%s>\n", name);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bearer_disable -
|
||||
*
|
||||
* Note: This routine assumes caller holds net_lock.
|
||||
*/
|
||||
|
||||
static int bearer_disable(const char *name)
|
||||
{
|
||||
struct bearer *b_ptr;
|
||||
struct link *l_ptr;
|
||||
struct link *temp_l_ptr;
|
||||
|
||||
if (tipc_mode != TIPC_NET_MODE)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
b_ptr = bearer_find(name);
|
||||
if (!b_ptr) {
|
||||
warn("Attempt to disable unknown bearer <%s>\n", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
disc_stop_link_req(b_ptr->link_req);
|
||||
spin_lock_bh(&b_ptr->publ.lock);
|
||||
b_ptr->link_req = NULL;
|
||||
b_ptr->publ.blocked = 1;
|
||||
if (b_ptr->media->disable_bearer) {
|
||||
spin_unlock_bh(&b_ptr->publ.lock);
|
||||
write_unlock_bh(&net_lock);
|
||||
b_ptr->media->disable_bearer(&b_ptr->publ);
|
||||
write_lock_bh(&net_lock);
|
||||
spin_lock_bh(&b_ptr->publ.lock);
|
||||
}
|
||||
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
|
||||
link_delete(l_ptr);
|
||||
}
|
||||
spin_unlock_bh(&b_ptr->publ.lock);
|
||||
info("Disabled bearer <%s>\n", name);
|
||||
memset(b_ptr, 0, sizeof(struct bearer));
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
int tipc_disable_bearer(const char *name)
|
||||
{
|
||||
int res;
|
||||
|
||||
write_lock_bh(&net_lock);
|
||||
res = bearer_disable(name);
|
||||
write_unlock_bh(&net_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int bearer_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
write_lock_bh(&net_lock);
|
||||
bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
|
||||
media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC);
|
||||
if (bearers && media_list) {
|
||||
memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer));
|
||||
memset(media_list, 0, MAX_MEDIA * sizeof(struct media));
|
||||
res = TIPC_OK;
|
||||
} else {
|
||||
kfree(bearers);
|
||||
kfree(media_list);
|
||||
bearers = 0;
|
||||
media_list = 0;
|
||||
res = -ENOMEM;
|
||||
}
|
||||
write_unlock_bh(&net_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
void bearer_stop(void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (!bearers)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_BEARERS; i++) {
|
||||
if (bearers[i].active)
|
||||
bearers[i].publ.blocked = 1;
|
||||
}
|
||||
for (i = 0; i < MAX_BEARERS; i++) {
|
||||
if (bearers[i].active)
|
||||
bearer_disable(bearers[i].publ.name);
|
||||
}
|
||||
kfree(bearers);
|
||||
kfree(media_list);
|
||||
bearers = 0;
|
||||
media_list = 0;
|
||||
media_count = 0;
|
||||
}
|
||||
|
||||
|
169
net/tipc/bearer.h
Normal file
169
net/tipc/bearer.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* net/tipc/bearer.h: Include file for TIPC bearer code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_BEARER_H
|
||||
#define _TIPC_BEARER_H
|
||||
|
||||
#include <net/tipc/tipc_bearer.h>
|
||||
#include "bcast.h"
|
||||
|
||||
#define MAX_BEARERS 8
|
||||
#define MAX_MEDIA 4
|
||||
|
||||
|
||||
/**
|
||||
* struct media - TIPC media information available to internal users
|
||||
* @send_msg: routine which handles buffer transmission
|
||||
* @enable_bearer: routine which enables a bearer
|
||||
* @disable_bearer: routine which disables a bearer
|
||||
* @addr2str: routine which converts bearer's address to string form
|
||||
* @bcast_addr: media address used in broadcasting
|
||||
* @bcast: non-zero if media supports broadcasting [currently mandatory]
|
||||
* @priority: default link (and bearer) priority
|
||||
* @tolerance: default time (in ms) before declaring link failure
|
||||
* @window: default window (in packets) before declaring link congestion
|
||||
* @type_id: TIPC media identifier [defined in tipc_bearer.h]
|
||||
* @name: media name
|
||||
*/
|
||||
|
||||
struct media {
|
||||
int (*send_msg)(struct sk_buff *buf,
|
||||
struct tipc_bearer *b_ptr,
|
||||
struct tipc_media_addr *dest);
|
||||
int (*enable_bearer)(struct tipc_bearer *b_ptr);
|
||||
void (*disable_bearer)(struct tipc_bearer *b_ptr);
|
||||
char *(*addr2str)(struct tipc_media_addr *a,
|
||||
char *str_buf, int str_size);
|
||||
struct tipc_media_addr bcast_addr;
|
||||
int bcast;
|
||||
u32 priority;
|
||||
u32 tolerance;
|
||||
u32 window;
|
||||
u32 type_id;
|
||||
char name[TIPC_MAX_MEDIA_NAME];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bearer - TIPC bearer information available to internal users
|
||||
* @publ: bearer information available to privileged users
|
||||
* @media: ptr to media structure associated with bearer
|
||||
* @priority: default link priority for bearer
|
||||
* @detect_scope: network address mask used during automatic link creation
|
||||
* @identity: array index of this bearer within TIPC bearer array
|
||||
* @link_req: ptr to (optional) structure making periodic link setup requests
|
||||
* @links: list of non-congested links associated with bearer
|
||||
* @cong_links: list of congested links associated with bearer
|
||||
* @continue_count: # of times bearer has resumed after congestion or blocking
|
||||
* @active: non-zero if bearer structure is represents a bearer
|
||||
* @net_plane: network plane ('A' through 'H') currently associated with bearer
|
||||
* @nodes: indicates which nodes in cluster can be reached through bearer
|
||||
*/
|
||||
|
||||
struct bearer {
|
||||
struct tipc_bearer publ;
|
||||
struct media *media;
|
||||
u32 priority;
|
||||
u32 detect_scope;
|
||||
u32 identity;
|
||||
struct link_req *link_req;
|
||||
struct list_head links;
|
||||
struct list_head cong_links;
|
||||
u32 continue_count;
|
||||
int active;
|
||||
char net_plane;
|
||||
struct node_map nodes;
|
||||
};
|
||||
|
||||
struct bearer_name {
|
||||
char media_name[TIPC_MAX_MEDIA_NAME];
|
||||
char if_name[TIPC_MAX_IF_NAME];
|
||||
};
|
||||
|
||||
struct link;
|
||||
|
||||
extern struct bearer *bearers;
|
||||
|
||||
void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
|
||||
struct sk_buff *media_get_names(void);
|
||||
|
||||
struct sk_buff *bearer_get_names(void);
|
||||
void bearer_add_dest(struct bearer *b_ptr, u32 dest);
|
||||
void bearer_remove_dest(struct bearer *b_ptr, u32 dest);
|
||||
void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);
|
||||
struct bearer *bearer_find_interface(const char *if_name);
|
||||
int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr);
|
||||
int bearer_init(void);
|
||||
void bearer_stop(void);
|
||||
int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr,
|
||||
struct tipc_media_addr *dest);
|
||||
void bearer_lock_push(struct bearer *b_ptr);
|
||||
|
||||
|
||||
/**
|
||||
* bearer_send- sends buffer to destination over bearer
|
||||
*
|
||||
* Returns true (1) if successful, or false (0) if unable to send
|
||||
*
|
||||
* IMPORTANT:
|
||||
* The media send routine must not alter the buffer being passed in
|
||||
* as it may be needed for later retransmission!
|
||||
*
|
||||
* If the media send routine returns a non-zero value (indicating that
|
||||
* it was unable to send the buffer), it must:
|
||||
* 1) mark the bearer as blocked,
|
||||
* 2) call tipc_continue() once the bearer is able to send again.
|
||||
* Media types that are unable to meet these two critera must ensure their
|
||||
* send routine always returns success -- even if the buffer was not sent --
|
||||
* and let TIPC's link code deal with the undelivered message.
|
||||
*/
|
||||
|
||||
static inline int bearer_send(struct bearer *b_ptr, struct sk_buff *buf,
|
||||
struct tipc_media_addr *dest)
|
||||
{
|
||||
return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* bearer_congested - determines if bearer is currently congested
|
||||
*/
|
||||
|
||||
static inline int bearer_congested(struct bearer *b_ptr, struct link *l_ptr)
|
||||
{
|
||||
if (unlikely(b_ptr->publ.blocked))
|
||||
return 1;
|
||||
if (likely(list_empty(&b_ptr->cong_links)))
|
||||
return 0;
|
||||
return !bearer_resolve_congestion(b_ptr, l_ptr);
|
||||
}
|
||||
|
||||
#endif
|
573
net/tipc/cluster.c
Normal file
573
net/tipc/cluster.c
Normal file
|
@ -0,0 +1,573 @@
|
|||
/*
|
||||
* net/tipc/cluster.c: TIPC cluster management routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "cluster.h"
|
||||
#include "addr.h"
|
||||
#include "node_subscr.h"
|
||||
#include "link.h"
|
||||
#include "node.h"
|
||||
#include "net.h"
|
||||
#include "msg.h"
|
||||
#include "bearer.h"
|
||||
|
||||
void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf,
|
||||
u32 lower, u32 upper);
|
||||
struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest);
|
||||
|
||||
struct node **local_nodes = 0;
|
||||
struct node_map cluster_bcast_nodes = {0,{0,}};
|
||||
u32 highest_allowed_slave = 0;
|
||||
|
||||
struct cluster *cluster_create(u32 addr)
|
||||
{
|
||||
struct _zone *z_ptr;
|
||||
struct cluster *c_ptr;
|
||||
int max_nodes;
|
||||
int alloc;
|
||||
|
||||
c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC);
|
||||
if (c_ptr == NULL)
|
||||
return 0;
|
||||
memset(c_ptr, 0, sizeof(*c_ptr));
|
||||
|
||||
c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
|
||||
if (in_own_cluster(addr))
|
||||
max_nodes = LOWEST_SLAVE + tipc_max_slaves;
|
||||
else
|
||||
max_nodes = tipc_max_nodes + 1;
|
||||
alloc = sizeof(void *) * (max_nodes + 1);
|
||||
c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC);
|
||||
if (c_ptr->nodes == NULL) {
|
||||
kfree(c_ptr);
|
||||
return 0;
|
||||
}
|
||||
memset(c_ptr->nodes, 0, alloc);
|
||||
if (in_own_cluster(addr))
|
||||
local_nodes = c_ptr->nodes;
|
||||
c_ptr->highest_slave = LOWEST_SLAVE - 1;
|
||||
c_ptr->highest_node = 0;
|
||||
|
||||
z_ptr = zone_find(tipc_zone(addr));
|
||||
if (z_ptr == NULL) {
|
||||
z_ptr = zone_create(addr);
|
||||
}
|
||||
if (z_ptr != NULL) {
|
||||
zone_attach_cluster(z_ptr, c_ptr);
|
||||
c_ptr->owner = z_ptr;
|
||||
}
|
||||
else {
|
||||
kfree(c_ptr);
|
||||
c_ptr = 0;
|
||||
}
|
||||
|
||||
return c_ptr;
|
||||
}
|
||||
|
||||
void cluster_delete(struct cluster *c_ptr)
|
||||
{
|
||||
u32 n_num;
|
||||
|
||||
if (!c_ptr)
|
||||
return;
|
||||
for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) {
|
||||
node_delete(c_ptr->nodes[n_num]);
|
||||
}
|
||||
for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) {
|
||||
node_delete(c_ptr->nodes[n_num]);
|
||||
}
|
||||
kfree(c_ptr->nodes);
|
||||
kfree(c_ptr);
|
||||
}
|
||||
|
||||
u32 cluster_next_node(struct cluster *c_ptr, u32 addr)
|
||||
{
|
||||
struct node *n_ptr;
|
||||
u32 n_num = tipc_node(addr) + 1;
|
||||
|
||||
if (!c_ptr)
|
||||
return addr;
|
||||
for (; n_num <= c_ptr->highest_node; n_num++) {
|
||||
n_ptr = c_ptr->nodes[n_num];
|
||||
if (n_ptr && node_has_active_links(n_ptr))
|
||||
return n_ptr->addr;
|
||||
}
|
||||
for (n_num = 1; n_num < tipc_node(addr); n_num++) {
|
||||
n_ptr = c_ptr->nodes[n_num];
|
||||
if (n_ptr && node_has_active_links(n_ptr))
|
||||
return n_ptr->addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr)
|
||||
{
|
||||
u32 n_num = tipc_node(n_ptr->addr);
|
||||
u32 max_n_num = tipc_max_nodes;
|
||||
|
||||
if (in_own_cluster(n_ptr->addr))
|
||||
max_n_num = highest_allowed_slave;
|
||||
assert(n_num > 0);
|
||||
assert(n_num <= max_n_num);
|
||||
assert(c_ptr->nodes[n_num] == 0);
|
||||
c_ptr->nodes[n_num] = n_ptr;
|
||||
if (n_num > c_ptr->highest_node)
|
||||
c_ptr->highest_node = n_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* cluster_select_router - select router to a cluster
|
||||
*
|
||||
* Uses deterministic and fair algorithm.
|
||||
*/
|
||||
|
||||
u32 cluster_select_router(struct cluster *c_ptr, u32 ref)
|
||||
{
|
||||
u32 n_num;
|
||||
u32 ulim = c_ptr->highest_node;
|
||||
u32 mask;
|
||||
u32 tstart;
|
||||
|
||||
assert(!in_own_cluster(c_ptr->addr));
|
||||
if (!ulim)
|
||||
return 0;
|
||||
|
||||
/* Start entry must be random */
|
||||
mask = tipc_max_nodes;
|
||||
while (mask > ulim)
|
||||
mask >>= 1;
|
||||
tstart = ref & mask;
|
||||
n_num = tstart;
|
||||
|
||||
/* Lookup upwards with wrap-around */
|
||||
do {
|
||||
if (node_is_up(c_ptr->nodes[n_num]))
|
||||
break;
|
||||
} while (++n_num <= ulim);
|
||||
if (n_num > ulim) {
|
||||
n_num = 1;
|
||||
do {
|
||||
if (node_is_up(c_ptr->nodes[n_num]))
|
||||
break;
|
||||
} while (++n_num < tstart);
|
||||
if (n_num == tstart)
|
||||
return 0;
|
||||
}
|
||||
assert(n_num <= ulim);
|
||||
return node_select_router(c_ptr->nodes[n_num], ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* cluster_select_node - select destination node within a remote cluster
|
||||
*
|
||||
* Uses deterministic and fair algorithm.
|
||||
*/
|
||||
|
||||
struct node *cluster_select_node(struct cluster *c_ptr, u32 selector)
|
||||
{
|
||||
u32 n_num;
|
||||
u32 mask = tipc_max_nodes;
|
||||
u32 start_entry;
|
||||
|
||||
assert(!in_own_cluster(c_ptr->addr));
|
||||
if (!c_ptr->highest_node)
|
||||
return 0;
|
||||
|
||||
/* Start entry must be random */
|
||||
while (mask > c_ptr->highest_node) {
|
||||
mask >>= 1;
|
||||
}
|
||||
start_entry = (selector & mask) ? selector & mask : 1u;
|
||||
assert(start_entry <= c_ptr->highest_node);
|
||||
|
||||
/* Lookup upwards with wrap-around */
|
||||
for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) {
|
||||
if (node_has_active_links(c_ptr->nodes[n_num]))
|
||||
return c_ptr->nodes[n_num];
|
||||
}
|
||||
for (n_num = 1; n_num < start_entry; n_num++) {
|
||||
if (node_has_active_links(c_ptr->nodes[n_num]))
|
||||
return c_ptr->nodes[n_num];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routing table management: See description in node.c
|
||||
*/
|
||||
|
||||
struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest)
|
||||
{
|
||||
u32 size = INT_H_SIZE + data_size;
|
||||
struct sk_buff *buf = buf_acquire(size);
|
||||
struct tipc_msg *msg;
|
||||
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
memset((char *)msg, 0, size);
|
||||
msg_init(msg, ROUTE_DISTRIBUTOR, 0, TIPC_OK, INT_H_SIZE, dest);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest,
|
||||
u32 lower, u32 upper)
|
||||
{
|
||||
struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr);
|
||||
struct tipc_msg *msg;
|
||||
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
msg_set_remote_node(msg, dest);
|
||||
msg_set_type(msg, ROUTE_ADDITION);
|
||||
cluster_multicast(c_ptr, buf, lower, upper);
|
||||
} else {
|
||||
warn("Memory squeeze: broadcast of new route failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest,
|
||||
u32 lower, u32 upper)
|
||||
{
|
||||
struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr);
|
||||
struct tipc_msg *msg;
|
||||
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
msg_set_remote_node(msg, dest);
|
||||
msg_set_type(msg, ROUTE_REMOVAL);
|
||||
cluster_multicast(c_ptr, buf, lower, upper);
|
||||
} else {
|
||||
warn("Memory squeeze: broadcast of lost route failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct tipc_msg *msg;
|
||||
u32 highest = c_ptr->highest_slave;
|
||||
u32 n_num;
|
||||
int send = 0;
|
||||
|
||||
assert(!is_slave(dest));
|
||||
assert(in_own_cluster(dest));
|
||||
assert(in_own_cluster(c_ptr->addr));
|
||||
if (highest <= LOWEST_SLAVE)
|
||||
return;
|
||||
buf = cluster_prepare_routing_msg(highest - LOWEST_SLAVE + 1,
|
||||
c_ptr->addr);
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
msg_set_remote_node(msg, c_ptr->addr);
|
||||
msg_set_type(msg, SLAVE_ROUTING_TABLE);
|
||||
for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) {
|
||||
if (c_ptr->nodes[n_num] &&
|
||||
node_has_active_links(c_ptr->nodes[n_num])) {
|
||||
send = 1;
|
||||
msg_set_dataoctet(msg, n_num);
|
||||
}
|
||||
}
|
||||
if (send)
|
||||
link_send(buf, dest, dest);
|
||||
else
|
||||
buf_discard(buf);
|
||||
} else {
|
||||
warn("Memory squeeze: broadcast of lost route failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct tipc_msg *msg;
|
||||
u32 highest = c_ptr->highest_node;
|
||||
u32 n_num;
|
||||
int send = 0;
|
||||
|
||||
if (in_own_cluster(c_ptr->addr))
|
||||
return;
|
||||
assert(!is_slave(dest));
|
||||
assert(in_own_cluster(dest));
|
||||
highest = c_ptr->highest_node;
|
||||
buf = cluster_prepare_routing_msg(highest + 1, c_ptr->addr);
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
msg_set_remote_node(msg, c_ptr->addr);
|
||||
msg_set_type(msg, EXT_ROUTING_TABLE);
|
||||
for (n_num = 1; n_num <= highest; n_num++) {
|
||||
if (c_ptr->nodes[n_num] &&
|
||||
node_has_active_links(c_ptr->nodes[n_num])) {
|
||||
send = 1;
|
||||
msg_set_dataoctet(msg, n_num);
|
||||
}
|
||||
}
|
||||
if (send)
|
||||
link_send(buf, dest, dest);
|
||||
else
|
||||
buf_discard(buf);
|
||||
} else {
|
||||
warn("Memory squeeze: broadcast of external route failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void cluster_send_local_routes(struct cluster *c_ptr, u32 dest)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct tipc_msg *msg;
|
||||
u32 highest = c_ptr->highest_node;
|
||||
u32 n_num;
|
||||
int send = 0;
|
||||
|
||||
assert(is_slave(dest));
|
||||
assert(in_own_cluster(c_ptr->addr));
|
||||
buf = cluster_prepare_routing_msg(highest, c_ptr->addr);
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
msg_set_remote_node(msg, c_ptr->addr);
|
||||
msg_set_type(msg, LOCAL_ROUTING_TABLE);
|
||||
for (n_num = 1; n_num <= highest; n_num++) {
|
||||
if (c_ptr->nodes[n_num] &&
|
||||
node_has_active_links(c_ptr->nodes[n_num])) {
|
||||
send = 1;
|
||||
msg_set_dataoctet(msg, n_num);
|
||||
}
|
||||
}
|
||||
if (send)
|
||||
link_send(buf, dest, dest);
|
||||
else
|
||||
buf_discard(buf);
|
||||
} else {
|
||||
warn("Memory squeeze: broadcast of local route failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void cluster_recv_routing_table(struct sk_buff *buf)
|
||||
{
|
||||
struct tipc_msg *msg = buf_msg(buf);
|
||||
struct cluster *c_ptr;
|
||||
struct node *n_ptr;
|
||||
unchar *node_table;
|
||||
u32 table_size;
|
||||
u32 router;
|
||||
u32 rem_node = msg_remote_node(msg);
|
||||
u32 z_num;
|
||||
u32 c_num;
|
||||
u32 n_num;
|
||||
|
||||
c_ptr = cluster_find(rem_node);
|
||||
if (!c_ptr) {
|
||||
c_ptr = cluster_create(rem_node);
|
||||
if (!c_ptr) {
|
||||
buf_discard(buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
node_table = buf->data + msg_hdr_sz(msg);
|
||||
table_size = msg_size(msg) - msg_hdr_sz(msg);
|
||||
router = msg_prevnode(msg);
|
||||
z_num = tipc_zone(rem_node);
|
||||
c_num = tipc_cluster(rem_node);
|
||||
|
||||
switch (msg_type(msg)) {
|
||||
case LOCAL_ROUTING_TABLE:
|
||||
assert(is_slave(tipc_own_addr));
|
||||
case EXT_ROUTING_TABLE:
|
||||
for (n_num = 1; n_num < table_size; n_num++) {
|
||||
if (node_table[n_num]) {
|
||||
u32 addr = tipc_addr(z_num, c_num, n_num);
|
||||
n_ptr = c_ptr->nodes[n_num];
|
||||
if (!n_ptr) {
|
||||
n_ptr = node_create(addr);
|
||||
}
|
||||
if (n_ptr)
|
||||
node_add_router(n_ptr, router);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SLAVE_ROUTING_TABLE:
|
||||
assert(!is_slave(tipc_own_addr));
|
||||
assert(in_own_cluster(c_ptr->addr));
|
||||
for (n_num = 1; n_num < table_size; n_num++) {
|
||||
if (node_table[n_num]) {
|
||||
u32 slave_num = n_num + LOWEST_SLAVE;
|
||||
u32 addr = tipc_addr(z_num, c_num, slave_num);
|
||||
n_ptr = c_ptr->nodes[slave_num];
|
||||
if (!n_ptr) {
|
||||
n_ptr = node_create(addr);
|
||||
}
|
||||
if (n_ptr)
|
||||
node_add_router(n_ptr, router);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ROUTE_ADDITION:
|
||||
if (!is_slave(tipc_own_addr)) {
|
||||
assert(!in_own_cluster(c_ptr->addr)
|
||||
|| is_slave(rem_node));
|
||||
} else {
|
||||
assert(in_own_cluster(c_ptr->addr)
|
||||
&& !is_slave(rem_node));
|
||||
}
|
||||
n_ptr = c_ptr->nodes[tipc_node(rem_node)];
|
||||
if (!n_ptr)
|
||||
n_ptr = node_create(rem_node);
|
||||
if (n_ptr)
|
||||
node_add_router(n_ptr, router);
|
||||
break;
|
||||
case ROUTE_REMOVAL:
|
||||
if (!is_slave(tipc_own_addr)) {
|
||||
assert(!in_own_cluster(c_ptr->addr)
|
||||
|| is_slave(rem_node));
|
||||
} else {
|
||||
assert(in_own_cluster(c_ptr->addr)
|
||||
&& !is_slave(rem_node));
|
||||
}
|
||||
n_ptr = c_ptr->nodes[tipc_node(rem_node)];
|
||||
if (n_ptr)
|
||||
node_remove_router(n_ptr, router);
|
||||
break;
|
||||
default:
|
||||
assert(!"Illegal routing manager message received\n");
|
||||
}
|
||||
buf_discard(buf);
|
||||
}
|
||||
|
||||
void cluster_remove_as_router(struct cluster *c_ptr, u32 router)
|
||||
{
|
||||
u32 start_entry;
|
||||
u32 tstop;
|
||||
u32 n_num;
|
||||
|
||||
if (is_slave(router))
|
||||
return; /* Slave nodes can not be routers */
|
||||
|
||||
if (in_own_cluster(c_ptr->addr)) {
|
||||
start_entry = LOWEST_SLAVE;
|
||||
tstop = c_ptr->highest_slave;
|
||||
} else {
|
||||
start_entry = 1;
|
||||
tstop = c_ptr->highest_node;
|
||||
}
|
||||
|
||||
for (n_num = start_entry; n_num <= tstop; n_num++) {
|
||||
if (c_ptr->nodes[n_num]) {
|
||||
node_remove_router(c_ptr->nodes[n_num], router);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cluster_multicast - multicast message to local nodes
|
||||
*/
|
||||
|
||||
void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf,
|
||||
u32 lower, u32 upper)
|
||||
{
|
||||
struct sk_buff *buf_copy;
|
||||
struct node *n_ptr;
|
||||
u32 n_num;
|
||||
u32 tstop;
|
||||
|
||||
assert(lower <= upper);
|
||||
assert(((lower >= 1) && (lower <= tipc_max_nodes)) ||
|
||||
((lower >= LOWEST_SLAVE) && (lower <= highest_allowed_slave)));
|
||||
assert(((upper >= 1) && (upper <= tipc_max_nodes)) ||
|
||||
((upper >= LOWEST_SLAVE) && (upper <= highest_allowed_slave)));
|
||||
assert(in_own_cluster(c_ptr->addr));
|
||||
|
||||
tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node;
|
||||
if (tstop > upper)
|
||||
tstop = upper;
|
||||
for (n_num = lower; n_num <= tstop; n_num++) {
|
||||
n_ptr = c_ptr->nodes[n_num];
|
||||
if (n_ptr && node_has_active_links(n_ptr)) {
|
||||
buf_copy = skb_copy(buf, GFP_ATOMIC);
|
||||
if (buf_copy == NULL)
|
||||
break;
|
||||
msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
|
||||
link_send(buf_copy, n_ptr->addr, n_ptr->addr);
|
||||
}
|
||||
}
|
||||
buf_discard(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* cluster_broadcast - broadcast message to all nodes within cluster
|
||||
*/
|
||||
|
||||
void cluster_broadcast(struct sk_buff *buf)
|
||||
{
|
||||
struct sk_buff *buf_copy;
|
||||
struct cluster *c_ptr;
|
||||
struct node *n_ptr;
|
||||
u32 n_num;
|
||||
u32 tstart;
|
||||
u32 tstop;
|
||||
u32 node_type;
|
||||
|
||||
if (tipc_mode == TIPC_NET_MODE) {
|
||||
c_ptr = cluster_find(tipc_own_addr);
|
||||
assert(in_own_cluster(c_ptr->addr)); /* For now */
|
||||
|
||||
/* Send to standard nodes, then repeat loop sending to slaves */
|
||||
tstart = 1;
|
||||
tstop = c_ptr->highest_node;
|
||||
for (node_type = 1; node_type <= 2; node_type++) {
|
||||
for (n_num = tstart; n_num <= tstop; n_num++) {
|
||||
n_ptr = c_ptr->nodes[n_num];
|
||||
if (n_ptr && node_has_active_links(n_ptr)) {
|
||||
buf_copy = skb_copy(buf, GFP_ATOMIC);
|
||||
if (buf_copy == NULL)
|
||||
goto exit;
|
||||
msg_set_destnode(buf_msg(buf_copy),
|
||||
n_ptr->addr);
|
||||
link_send(buf_copy, n_ptr->addr,
|
||||
n_ptr->addr);
|
||||
}
|
||||
}
|
||||
tstart = LOWEST_SLAVE;
|
||||
tstop = c_ptr->highest_slave;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
buf_discard(buf);
|
||||
}
|
||||
|
||||
int cluster_init(void)
|
||||
{
|
||||
highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves;
|
||||
return cluster_create(tipc_own_addr) ? TIPC_OK : -ENOMEM;
|
||||
}
|
||||
|
89
net/tipc/cluster.h
Normal file
89
net/tipc/cluster.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* net/tipc/cluster.h: Include file for TIPC cluster management routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_CLUSTER_H
|
||||
#define _TIPC_CLUSTER_H
|
||||
|
||||
#include "addr.h"
|
||||
#include "zone.h"
|
||||
|
||||
#define LOWEST_SLAVE 2048u
|
||||
|
||||
/**
|
||||
* struct cluster - TIPC cluster structure
|
||||
* @addr: network address of cluster
|
||||
* @owner: pointer to zone that cluster belongs to
|
||||
* @nodes: array of pointers to all nodes within cluster
|
||||
* @highest_node: id of highest numbered node within cluster
|
||||
* @highest_slave: (used for secondary node support)
|
||||
*/
|
||||
|
||||
struct cluster {
|
||||
u32 addr;
|
||||
struct _zone *owner;
|
||||
struct node **nodes;
|
||||
u32 highest_node;
|
||||
u32 highest_slave;
|
||||
};
|
||||
|
||||
|
||||
extern struct node **local_nodes;
|
||||
extern u32 highest_allowed_slave;
|
||||
extern struct node_map cluster_bcast_nodes;
|
||||
|
||||
void cluster_remove_as_router(struct cluster *c_ptr, u32 router);
|
||||
void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest);
|
||||
struct node *cluster_select_node(struct cluster *c_ptr, u32 selector);
|
||||
u32 cluster_select_router(struct cluster *c_ptr, u32 ref);
|
||||
void cluster_recv_routing_table(struct sk_buff *buf);
|
||||
struct cluster *cluster_create(u32 addr);
|
||||
void cluster_delete(struct cluster *c_ptr);
|
||||
void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr);
|
||||
void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest);
|
||||
void cluster_broadcast(struct sk_buff *buf);
|
||||
int cluster_init(void);
|
||||
u32 cluster_next_node(struct cluster *c_ptr, u32 addr);
|
||||
void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
|
||||
void cluster_send_local_routes(struct cluster *c_ptr, u32 dest);
|
||||
void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
|
||||
|
||||
static inline struct cluster *cluster_find(u32 addr)
|
||||
{
|
||||
struct _zone *z_ptr = zone_find(addr);
|
||||
|
||||
if (z_ptr)
|
||||
return z_ptr->clusters[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
715
net/tipc/config.c
Normal file
715
net/tipc/config.c
Normal file
|
@ -0,0 +1,715 @@
|
|||
/*
|
||||
* net/tipc/config.c: TIPC configuration management code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "dbg.h"
|
||||
#include "bearer.h"
|
||||
#include "port.h"
|
||||
#include "link.h"
|
||||
#include "zone.h"
|
||||
#include "addr.h"
|
||||
#include "name_table.h"
|
||||
#include "node.h"
|
||||
#include "config.h"
|
||||
#include "discover.h"
|
||||
|
||||
struct subscr_data {
|
||||
char usr_handle[8];
|
||||
u32 domain;
|
||||
u32 port_ref;
|
||||
struct list_head subd_list;
|
||||
};
|
||||
|
||||
struct manager {
|
||||
u32 user_ref;
|
||||
u32 port_ref;
|
||||
u32 subscr_ref;
|
||||
u32 link_subscriptions;
|
||||
struct list_head link_subscribers;
|
||||
};
|
||||
|
||||
static struct manager mng = { 0};
|
||||
|
||||
static spinlock_t config_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static const void *req_tlv_area; /* request message TLV area */
|
||||
static int req_tlv_space; /* request message TLV area size */
|
||||
static int rep_headroom; /* reply message headroom to use */
|
||||
|
||||
|
||||
void cfg_link_event(u32 addr, char *name, int up)
|
||||
{
|
||||
/* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */
|
||||
}
|
||||
|
||||
|
||||
struct sk_buff *cfg_reply_alloc(int payload_size)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
|
||||
buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC);
|
||||
if (buf)
|
||||
skb_reserve(buf, rep_headroom);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int cfg_append_tlv(struct sk_buff *buf, int tlv_type,
|
||||
void *tlv_data, int tlv_data_size)
|
||||
{
|
||||
struct tlv_desc *tlv = (struct tlv_desc *)buf->tail;
|
||||
int new_tlv_space = TLV_SPACE(tlv_data_size);
|
||||
|
||||
if (skb_tailroom(buf) < new_tlv_space) {
|
||||
dbg("cfg_append_tlv unable to append TLV\n");
|
||||
return 0;
|
||||
}
|
||||
skb_put(buf, new_tlv_space);
|
||||
tlv->tlv_type = htons(tlv_type);
|
||||
tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size));
|
||||
if (tlv_data_size && tlv_data)
|
||||
memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
u32 value_net;
|
||||
|
||||
buf = cfg_reply_alloc(TLV_SPACE(sizeof(value)));
|
||||
if (buf) {
|
||||
value_net = htonl(value);
|
||||
cfg_append_tlv(buf, tlv_type, &value_net,
|
||||
sizeof(value_net));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
int string_len = strlen(string) + 1;
|
||||
|
||||
buf = cfg_reply_alloc(TLV_SPACE(string_len));
|
||||
if (buf)
|
||||
cfg_append_tlv(buf, tlv_type, string, string_len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/* Now obsolete code for handling commands not yet implemented the new way */
|
||||
|
||||
int tipc_cfg_cmd(const struct tipc_cmd_msg * msg,
|
||||
char *data,
|
||||
u32 sz,
|
||||
u32 *ret_size,
|
||||
struct tipc_portid *orig)
|
||||
{
|
||||
int rv = -EINVAL;
|
||||
u32 cmd = msg->cmd;
|
||||
|
||||
*ret_size = 0;
|
||||
switch (cmd) {
|
||||
case TIPC_REMOVE_LINK:
|
||||
case TIPC_CMD_BLOCK_LINK:
|
||||
case TIPC_CMD_UNBLOCK_LINK:
|
||||
if (!cfg_check_connection(orig))
|
||||
rv = link_control(msg->argv.link_name, msg->cmd, 0);
|
||||
break;
|
||||
case TIPC_ESTABLISH:
|
||||
{
|
||||
int connected;
|
||||
|
||||
tipc_isconnected(mng.conn_port_ref, &connected);
|
||||
if (connected || !orig) {
|
||||
rv = TIPC_FAILURE;
|
||||
break;
|
||||
}
|
||||
rv = tipc_connect2port(mng.conn_port_ref, orig);
|
||||
if (rv == TIPC_OK)
|
||||
orig = 0;
|
||||
break;
|
||||
}
|
||||
case TIPC_GET_PEER_ADDRESS:
|
||||
*ret_size = link_peer_addr(msg->argv.link_name, data, sz);
|
||||
break;
|
||||
case TIPC_GET_ROUTES:
|
||||
rv = TIPC_OK;
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
if (*ret_size)
|
||||
rv = TIPC_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void cfg_cmd_event(struct tipc_cmd_msg *msg,
|
||||
char *data,
|
||||
u32 sz,
|
||||
struct tipc_portid const *orig)
|
||||
{
|
||||
int rv = -EINVAL;
|
||||
struct tipc_cmd_result_msg rmsg;
|
||||
struct iovec msg_sect[2];
|
||||
int *arg;
|
||||
|
||||
msg->cmd = ntohl(msg->cmd);
|
||||
|
||||
cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect,
|
||||
data, 0);
|
||||
if (ntohl(msg->magic) != TIPC_MAGIC)
|
||||
goto exit;
|
||||
|
||||
switch (msg->cmd) {
|
||||
case TIPC_CREATE_LINK:
|
||||
if (!cfg_check_connection(orig))
|
||||
rv = disc_create_link(&msg->argv.create_link);
|
||||
break;
|
||||
case TIPC_LINK_SUBSCRIBE:
|
||||
{
|
||||
struct subscr_data *sub;
|
||||
|
||||
if (mng.link_subscriptions > 64)
|
||||
break;
|
||||
sub = (struct subscr_data *)kmalloc(sizeof(*sub),
|
||||
GFP_ATOMIC);
|
||||
if (sub == NULL) {
|
||||
warn("Memory squeeze; dropped remote link subscription\n");
|
||||
break;
|
||||
}
|
||||
INIT_LIST_HEAD(&sub->subd_list);
|
||||
tipc_createport(mng.user_ref,
|
||||
(void *)sub,
|
||||
TIPC_HIGH_IMPORTANCE,
|
||||
0,
|
||||
0,
|
||||
(tipc_conn_shutdown_event)cfg_linksubscr_cancel,
|
||||
0,
|
||||
0,
|
||||
(tipc_conn_msg_event)cfg_linksubscr_cancel,
|
||||
0,
|
||||
&sub->port_ref);
|
||||
if (!sub->port_ref) {
|
||||
kfree(sub);
|
||||
break;
|
||||
}
|
||||
memcpy(sub->usr_handle,msg->usr_handle,
|
||||
sizeof(sub->usr_handle));
|
||||
sub->domain = msg->argv.domain;
|
||||
list_add_tail(&sub->subd_list, &mng.link_subscribers);
|
||||
tipc_connect2port(sub->port_ref, orig);
|
||||
rmsg.retval = TIPC_OK;
|
||||
tipc_send(sub->port_ref, 2u, msg_sect);
|
||||
mng.link_subscriptions++;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig);
|
||||
}
|
||||
exit:
|
||||
rmsg.result_len = htonl(msg_sect[1].iov_len);
|
||||
rmsg.retval = htonl(rv);
|
||||
cfg_respond(msg_sect, 2u, orig);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sk_buff *cfg_enable_bearer(void)
|
||||
{
|
||||
struct tipc_bearer_config *args;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
|
||||
if (tipc_enable_bearer(args->name,
|
||||
ntohl(args->detect_scope),
|
||||
ntohl(args->priority)))
|
||||
return cfg_reply_error_string("unable to enable bearer");
|
||||
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_disable_bearer(void)
|
||||
{
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area)))
|
||||
return cfg_reply_error_string("unable to disable bearer");
|
||||
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_own_addr(void)
|
||||
{
|
||||
u32 addr;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
addr = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
addr = ntohl(addr);
|
||||
if (addr == tipc_own_addr)
|
||||
return cfg_reply_none();
|
||||
if (!addr_node_valid(addr))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (node address)");
|
||||
if (tipc_own_addr)
|
||||
return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (cannot change node address once assigned)");
|
||||
|
||||
spin_unlock_bh(&config_lock);
|
||||
stop_net();
|
||||
tipc_own_addr = addr;
|
||||
start_net();
|
||||
spin_lock_bh(&config_lock);
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_remote_mng(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
tipc_remote_management = (value != 0);
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_max_publications(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != delimit(value, 1, 65535))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (max publications must be 1-65535)");
|
||||
tipc_max_publications = value;
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_max_subscriptions(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != delimit(value, 1, 65535))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (max subscriptions must be 1-65535");
|
||||
tipc_max_subscriptions = value;
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_max_ports(void)
|
||||
{
|
||||
int orig_mode;
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != delimit(value, 127, 65535))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (max ports must be 127-65535)");
|
||||
|
||||
if (value == tipc_max_ports)
|
||||
return cfg_reply_none();
|
||||
|
||||
if (atomic_read(&tipc_user_count) > 2)
|
||||
return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (cannot change max ports while TIPC users exist)");
|
||||
|
||||
spin_unlock_bh(&config_lock);
|
||||
orig_mode = tipc_get_mode();
|
||||
if (orig_mode == TIPC_NET_MODE)
|
||||
stop_net();
|
||||
stop_core();
|
||||
tipc_max_ports = value;
|
||||
start_core();
|
||||
if (orig_mode == TIPC_NET_MODE)
|
||||
start_net();
|
||||
spin_lock_bh(&config_lock);
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *set_net_max(int value, int *parameter)
|
||||
{
|
||||
int orig_mode;
|
||||
|
||||
if (value != *parameter) {
|
||||
orig_mode = tipc_get_mode();
|
||||
if (orig_mode == TIPC_NET_MODE)
|
||||
stop_net();
|
||||
*parameter = value;
|
||||
if (orig_mode == TIPC_NET_MODE)
|
||||
start_net();
|
||||
}
|
||||
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_max_zones(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != delimit(value, 1, 255))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (max zones must be 1-255)");
|
||||
return set_net_max(value, &tipc_max_zones);
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_max_clusters(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != 1)
|
||||
return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (max clusters fixed at 1)");
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_max_nodes(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != delimit(value, 8, 2047))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (max nodes must be 8-2047)");
|
||||
return set_net_max(value, &tipc_max_nodes);
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_max_slaves(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != 0)
|
||||
return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (max secondary nodes fixed at 0)");
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
static struct sk_buff *cfg_set_netid(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != delimit(value, 1, 9999))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (network id must be 1-9999)");
|
||||
|
||||
if (tipc_own_addr)
|
||||
return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (cannot change network id once part of network)");
|
||||
|
||||
return set_net_max(value, &tipc_net_id);
|
||||
}
|
||||
|
||||
struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
|
||||
int request_space, int reply_headroom)
|
||||
{
|
||||
struct sk_buff *rep_tlv_buf;
|
||||
|
||||
spin_lock_bh(&config_lock);
|
||||
|
||||
/* Save request and reply details in a well-known location */
|
||||
|
||||
req_tlv_area = request_area;
|
||||
req_tlv_space = request_space;
|
||||
rep_headroom = reply_headroom;
|
||||
|
||||
/* Check command authorization */
|
||||
|
||||
if (likely(orig_node == tipc_own_addr)) {
|
||||
/* command is permitted */
|
||||
} else if (cmd >= 0x8000) {
|
||||
rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (cannot be done remotely)");
|
||||
goto exit;
|
||||
} else if (!tipc_remote_management) {
|
||||
rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NO_REMOTE);
|
||||
goto exit;
|
||||
}
|
||||
else if (cmd >= 0x4000) {
|
||||
u32 domain = 0;
|
||||
|
||||
if ((nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) ||
|
||||
(domain != orig_node)) {
|
||||
rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call appropriate processing routine */
|
||||
|
||||
switch (cmd) {
|
||||
case TIPC_CMD_NOOP:
|
||||
rep_tlv_buf = cfg_reply_none();
|
||||
break;
|
||||
case TIPC_CMD_GET_NODES:
|
||||
rep_tlv_buf = node_get_nodes(req_tlv_area, req_tlv_space);
|
||||
break;
|
||||
case TIPC_CMD_GET_LINKS:
|
||||
rep_tlv_buf = node_get_links(req_tlv_area, req_tlv_space);
|
||||
break;
|
||||
case TIPC_CMD_SHOW_LINK_STATS:
|
||||
rep_tlv_buf = link_cmd_show_stats(req_tlv_area, req_tlv_space);
|
||||
break;
|
||||
case TIPC_CMD_RESET_LINK_STATS:
|
||||
rep_tlv_buf = link_cmd_reset_stats(req_tlv_area, req_tlv_space);
|
||||
break;
|
||||
case TIPC_CMD_SHOW_NAME_TABLE:
|
||||
rep_tlv_buf = nametbl_get(req_tlv_area, req_tlv_space);
|
||||
break;
|
||||
case TIPC_CMD_GET_BEARER_NAMES:
|
||||
rep_tlv_buf = bearer_get_names();
|
||||
break;
|
||||
case TIPC_CMD_GET_MEDIA_NAMES:
|
||||
rep_tlv_buf = media_get_names();
|
||||
break;
|
||||
case TIPC_CMD_SHOW_PORTS:
|
||||
rep_tlv_buf = port_get_ports();
|
||||
break;
|
||||
#if 0
|
||||
case TIPC_CMD_SHOW_PORT_STATS:
|
||||
rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space);
|
||||
break;
|
||||
case TIPC_CMD_RESET_PORT_STATS:
|
||||
rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED);
|
||||
break;
|
||||
#endif
|
||||
case TIPC_CMD_SET_LOG_SIZE:
|
||||
rep_tlv_buf = log_resize(req_tlv_area, req_tlv_space);
|
||||
break;
|
||||
case TIPC_CMD_DUMP_LOG:
|
||||
rep_tlv_buf = log_dump();
|
||||
break;
|
||||
case TIPC_CMD_SET_LINK_TOL:
|
||||
case TIPC_CMD_SET_LINK_PRI:
|
||||
case TIPC_CMD_SET_LINK_WINDOW:
|
||||
rep_tlv_buf = link_cmd_config(req_tlv_area, req_tlv_space, cmd);
|
||||
break;
|
||||
case TIPC_CMD_ENABLE_BEARER:
|
||||
rep_tlv_buf = cfg_enable_bearer();
|
||||
break;
|
||||
case TIPC_CMD_DISABLE_BEARER:
|
||||
rep_tlv_buf = cfg_disable_bearer();
|
||||
break;
|
||||
case TIPC_CMD_SET_NODE_ADDR:
|
||||
rep_tlv_buf = cfg_set_own_addr();
|
||||
break;
|
||||
case TIPC_CMD_SET_REMOTE_MNG:
|
||||
rep_tlv_buf = cfg_set_remote_mng();
|
||||
break;
|
||||
case TIPC_CMD_SET_MAX_PORTS:
|
||||
rep_tlv_buf = cfg_set_max_ports();
|
||||
break;
|
||||
case TIPC_CMD_SET_MAX_PUBL:
|
||||
rep_tlv_buf = cfg_set_max_publications();
|
||||
break;
|
||||
case TIPC_CMD_SET_MAX_SUBSCR:
|
||||
rep_tlv_buf = cfg_set_max_subscriptions();
|
||||
break;
|
||||
case TIPC_CMD_SET_MAX_ZONES:
|
||||
rep_tlv_buf = cfg_set_max_zones();
|
||||
break;
|
||||
case TIPC_CMD_SET_MAX_CLUSTERS:
|
||||
rep_tlv_buf = cfg_set_max_clusters();
|
||||
break;
|
||||
case TIPC_CMD_SET_MAX_NODES:
|
||||
rep_tlv_buf = cfg_set_max_nodes();
|
||||
break;
|
||||
case TIPC_CMD_SET_MAX_SLAVES:
|
||||
rep_tlv_buf = cfg_set_max_slaves();
|
||||
break;
|
||||
case TIPC_CMD_SET_NETID:
|
||||
rep_tlv_buf = cfg_set_netid();
|
||||
break;
|
||||
case TIPC_CMD_GET_REMOTE_MNG:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_remote_management);
|
||||
break;
|
||||
case TIPC_CMD_GET_MAX_PORTS:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_max_ports);
|
||||
break;
|
||||
case TIPC_CMD_GET_MAX_PUBL:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_max_publications);
|
||||
break;
|
||||
case TIPC_CMD_GET_MAX_SUBSCR:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_max_subscriptions);
|
||||
break;
|
||||
case TIPC_CMD_GET_MAX_ZONES:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_max_zones);
|
||||
break;
|
||||
case TIPC_CMD_GET_MAX_CLUSTERS:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_max_clusters);
|
||||
break;
|
||||
case TIPC_CMD_GET_MAX_NODES:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_max_nodes);
|
||||
break;
|
||||
case TIPC_CMD_GET_MAX_SLAVES:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_max_slaves);
|
||||
break;
|
||||
case TIPC_CMD_GET_NETID:
|
||||
rep_tlv_buf = cfg_reply_unsigned(tipc_net_id);
|
||||
break;
|
||||
default:
|
||||
rep_tlv_buf = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return reply buffer */
|
||||
exit:
|
||||
spin_unlock_bh(&config_lock);
|
||||
return rep_tlv_buf;
|
||||
}
|
||||
|
||||
static void cfg_named_msg_event(void *userdata,
|
||||
u32 port_ref,
|
||||
struct sk_buff **buf,
|
||||
const unchar *msg,
|
||||
u32 size,
|
||||
u32 importance,
|
||||
struct tipc_portid const *orig,
|
||||
struct tipc_name_seq const *dest)
|
||||
{
|
||||
struct tipc_cfg_msg_hdr *req_hdr;
|
||||
struct tipc_cfg_msg_hdr *rep_hdr;
|
||||
struct sk_buff *rep_buf;
|
||||
|
||||
/* Validate configuration message header (ignore invalid message) */
|
||||
|
||||
req_hdr = (struct tipc_cfg_msg_hdr *)msg;
|
||||
if ((size < sizeof(*req_hdr)) ||
|
||||
(size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) ||
|
||||
(ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) {
|
||||
warn("discarded invalid configuration message\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate reply for request (if can't, return request) */
|
||||
|
||||
rep_buf = cfg_do_cmd(orig->node,
|
||||
ntohs(req_hdr->tcm_type),
|
||||
msg + sizeof(*req_hdr),
|
||||
size - sizeof(*req_hdr),
|
||||
BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
|
||||
if (rep_buf) {
|
||||
skb_push(rep_buf, sizeof(*rep_hdr));
|
||||
rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data;
|
||||
memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
|
||||
rep_hdr->tcm_len = htonl(rep_buf->len);
|
||||
rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
|
||||
} else {
|
||||
rep_buf = *buf;
|
||||
*buf = NULL;
|
||||
}
|
||||
|
||||
/* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */
|
||||
tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len);
|
||||
}
|
||||
|
||||
int cfg_init(void)
|
||||
{
|
||||
struct tipc_name_seq seq;
|
||||
int res;
|
||||
|
||||
memset(&mng, 0, sizeof(mng));
|
||||
INIT_LIST_HEAD(&mng.link_subscribers);
|
||||
|
||||
res = tipc_attach(&mng.user_ref, 0, 0);
|
||||
if (res)
|
||||
goto failed;
|
||||
|
||||
res = tipc_createport(mng.user_ref, 0, TIPC_CRITICAL_IMPORTANCE,
|
||||
NULL, NULL, NULL,
|
||||
NULL, cfg_named_msg_event, NULL,
|
||||
NULL, &mng.port_ref);
|
||||
if (res)
|
||||
goto failed;
|
||||
|
||||
seq.type = TIPC_CFG_SRV;
|
||||
seq.lower = seq.upper = tipc_own_addr;
|
||||
res = nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq);
|
||||
if (res)
|
||||
goto failed;
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
err("Unable to create configuration service\n");
|
||||
tipc_detach(mng.user_ref);
|
||||
mng.user_ref = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
void cfg_stop(void)
|
||||
{
|
||||
if (mng.user_ref) {
|
||||
tipc_detach(mng.user_ref);
|
||||
mng.user_ref = 0;
|
||||
}
|
||||
}
|
76
net/tipc/config.h
Normal file
76
net/tipc/config.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* net/tipc/config.h: Include file for TIPC configuration service code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_CONFIG_H
|
||||
#define _TIPC_CONFIG_H
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#include <linux/tipc.h>
|
||||
#include "link.h"
|
||||
|
||||
struct sk_buff *cfg_reply_alloc(int payload_size);
|
||||
int cfg_append_tlv(struct sk_buff *buf, int tlv_type,
|
||||
void *tlv_data, int tlv_data_size);
|
||||
struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value);
|
||||
struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string);
|
||||
|
||||
static inline struct sk_buff *cfg_reply_none(void)
|
||||
{
|
||||
return cfg_reply_alloc(0);
|
||||
}
|
||||
|
||||
static inline struct sk_buff *cfg_reply_unsigned(u32 value)
|
||||
{
|
||||
return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
|
||||
}
|
||||
|
||||
static inline struct sk_buff *cfg_reply_error_string(char *string)
|
||||
{
|
||||
return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
|
||||
}
|
||||
|
||||
static inline struct sk_buff *cfg_reply_ultra_string(char *string)
|
||||
{
|
||||
return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
|
||||
}
|
||||
|
||||
struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd,
|
||||
const void *req_tlv_area, int req_tlv_space,
|
||||
int headroom);
|
||||
|
||||
void cfg_link_event(u32 addr, char *name, int up);
|
||||
int cfg_init(void);
|
||||
void cfg_stop(void);
|
||||
|
||||
#endif
|
282
net/tipc/core.c
Normal file
282
net/tipc/core.c
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* net/tipc/core.c: TIPC module code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "dbg.h"
|
||||
#include "ref.h"
|
||||
#include "net.h"
|
||||
#include "user_reg.h"
|
||||
#include "name_table.h"
|
||||
#include "subscr.h"
|
||||
#include "config.h"
|
||||
|
||||
int eth_media_start(void);
|
||||
void eth_media_stop(void);
|
||||
int handler_start(void);
|
||||
void handler_stop(void);
|
||||
int socket_init(void);
|
||||
void socket_stop(void);
|
||||
int netlink_start(void);
|
||||
void netlink_stop(void);
|
||||
|
||||
#define MOD_NAME "tipc_start: "
|
||||
|
||||
#ifndef CONFIG_TIPC_ZONES
|
||||
#define CONFIG_TIPC_ZONES 3
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TIPC_CLUSTERS
|
||||
#define CONFIG_TIPC_CLUSTERS 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TIPC_NODES
|
||||
#define CONFIG_TIPC_NODES 255
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TIPC_SLAVE_NODES
|
||||
#define CONFIG_TIPC_SLAVE_NODES 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TIPC_PORTS
|
||||
#define CONFIG_TIPC_PORTS 8191
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TIPC_LOG
|
||||
#define CONFIG_TIPC_LOG 0
|
||||
#endif
|
||||
|
||||
/* global variables used by multiple sub-systems within TIPC */
|
||||
|
||||
int tipc_mode = TIPC_NOT_RUNNING;
|
||||
int tipc_random;
|
||||
atomic_t tipc_user_count = ATOMIC_INIT(0);
|
||||
|
||||
const char tipc_alphabet[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||
|
||||
/* configurable TIPC parameters */
|
||||
|
||||
u32 tipc_own_addr;
|
||||
int tipc_max_zones;
|
||||
int tipc_max_clusters;
|
||||
int tipc_max_nodes;
|
||||
int tipc_max_slaves;
|
||||
int tipc_max_ports;
|
||||
int tipc_max_subscriptions;
|
||||
int tipc_max_publications;
|
||||
int tipc_net_id;
|
||||
int tipc_remote_management;
|
||||
|
||||
|
||||
int tipc_get_mode(void)
|
||||
{
|
||||
return tipc_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* stop_net - shut down TIPC networking sub-systems
|
||||
*/
|
||||
|
||||
void stop_net(void)
|
||||
{
|
||||
eth_media_stop();
|
||||
tipc_stop_net();
|
||||
}
|
||||
|
||||
/**
|
||||
* start_net - start TIPC networking sub-systems
|
||||
*/
|
||||
|
||||
int start_net(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
if ((res = tipc_start_net()) ||
|
||||
(res = eth_media_start())) {
|
||||
stop_net();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* stop_core - switch TIPC from SINGLE NODE to NOT RUNNING mode
|
||||
*/
|
||||
|
||||
void stop_core(void)
|
||||
{
|
||||
if (tipc_mode != TIPC_NODE_MODE)
|
||||
return;
|
||||
|
||||
tipc_mode = TIPC_NOT_RUNNING;
|
||||
|
||||
netlink_stop();
|
||||
handler_stop();
|
||||
cfg_stop();
|
||||
subscr_stop();
|
||||
reg_stop();
|
||||
nametbl_stop();
|
||||
ref_table_stop();
|
||||
socket_stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* start_core - switch TIPC from NOT RUNNING to SINGLE NODE mode
|
||||
*/
|
||||
|
||||
int start_core(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (tipc_mode != TIPC_NOT_RUNNING)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
get_random_bytes(&tipc_random, sizeof(tipc_random));
|
||||
tipc_mode = TIPC_NODE_MODE;
|
||||
|
||||
if ((res = handler_start()) ||
|
||||
(res = ref_table_init(tipc_max_ports + tipc_max_subscriptions,
|
||||
tipc_random)) ||
|
||||
(res = reg_start()) ||
|
||||
(res = nametbl_init()) ||
|
||||
(res = k_signal((Handler)subscr_start, 0)) ||
|
||||
(res = k_signal((Handler)cfg_init, 0)) ||
|
||||
(res = netlink_start()) ||
|
||||
(res = socket_init())) {
|
||||
stop_core();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int __init tipc_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
log_reinit(CONFIG_TIPC_LOG);
|
||||
info("Activated (compiled " __DATE__ " " __TIME__ ")\n");
|
||||
|
||||
tipc_own_addr = 0;
|
||||
tipc_remote_management = 1;
|
||||
tipc_max_publications = 10000;
|
||||
tipc_max_subscriptions = 2000;
|
||||
tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536);
|
||||
tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511);
|
||||
tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1);
|
||||
tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047);
|
||||
tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047);
|
||||
tipc_net_id = 4711;
|
||||
|
||||
if ((res = start_core()))
|
||||
err("Unable to start in single node mode\n");
|
||||
else
|
||||
info("Started in single node mode\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
static void __exit tipc_exit(void)
|
||||
{
|
||||
stop_net();
|
||||
stop_core();
|
||||
info("Deactivated\n");
|
||||
log_stop();
|
||||
}
|
||||
|
||||
module_init(tipc_init);
|
||||
module_exit(tipc_exit);
|
||||
|
||||
MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* Native TIPC API for kernel-space applications (see tipc.h) */
|
||||
|
||||
EXPORT_SYMBOL(tipc_attach);
|
||||
EXPORT_SYMBOL(tipc_detach);
|
||||
EXPORT_SYMBOL(tipc_get_addr);
|
||||
EXPORT_SYMBOL(tipc_get_mode);
|
||||
EXPORT_SYMBOL(tipc_createport);
|
||||
EXPORT_SYMBOL(tipc_deleteport);
|
||||
EXPORT_SYMBOL(tipc_ownidentity);
|
||||
EXPORT_SYMBOL(tipc_portimportance);
|
||||
EXPORT_SYMBOL(tipc_set_portimportance);
|
||||
EXPORT_SYMBOL(tipc_portunreliable);
|
||||
EXPORT_SYMBOL(tipc_set_portunreliable);
|
||||
EXPORT_SYMBOL(tipc_portunreturnable);
|
||||
EXPORT_SYMBOL(tipc_set_portunreturnable);
|
||||
EXPORT_SYMBOL(tipc_publish);
|
||||
EXPORT_SYMBOL(tipc_withdraw);
|
||||
EXPORT_SYMBOL(tipc_connect2port);
|
||||
EXPORT_SYMBOL(tipc_disconnect);
|
||||
EXPORT_SYMBOL(tipc_shutdown);
|
||||
EXPORT_SYMBOL(tipc_isconnected);
|
||||
EXPORT_SYMBOL(tipc_peer);
|
||||
EXPORT_SYMBOL(tipc_ref_valid);
|
||||
EXPORT_SYMBOL(tipc_send);
|
||||
EXPORT_SYMBOL(tipc_send_buf);
|
||||
EXPORT_SYMBOL(tipc_send2name);
|
||||
EXPORT_SYMBOL(tipc_forward2name);
|
||||
EXPORT_SYMBOL(tipc_send_buf2name);
|
||||
EXPORT_SYMBOL(tipc_forward_buf2name);
|
||||
EXPORT_SYMBOL(tipc_send2port);
|
||||
EXPORT_SYMBOL(tipc_forward2port);
|
||||
EXPORT_SYMBOL(tipc_send_buf2port);
|
||||
EXPORT_SYMBOL(tipc_forward_buf2port);
|
||||
EXPORT_SYMBOL(tipc_multicast);
|
||||
/* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */
|
||||
EXPORT_SYMBOL(tipc_ispublished);
|
||||
EXPORT_SYMBOL(tipc_available_nodes);
|
||||
|
||||
/* TIPC API for external bearers (see tipc_bearer.h) */
|
||||
|
||||
EXPORT_SYMBOL(tipc_block_bearer);
|
||||
EXPORT_SYMBOL(tipc_continue);
|
||||
EXPORT_SYMBOL(tipc_disable_bearer);
|
||||
EXPORT_SYMBOL(tipc_enable_bearer);
|
||||
EXPORT_SYMBOL(tipc_recv_msg);
|
||||
EXPORT_SYMBOL(tipc_register_media);
|
||||
|
||||
/* TIPC API for external APIs (see tipc_port.h) */
|
||||
|
||||
EXPORT_SYMBOL(tipc_createport_raw);
|
||||
EXPORT_SYMBOL(tipc_set_msg_option);
|
||||
EXPORT_SYMBOL(tipc_reject_msg);
|
||||
EXPORT_SYMBOL(tipc_send_buf_fast);
|
||||
EXPORT_SYMBOL(tipc_acknowledge);
|
||||
EXPORT_SYMBOL(tipc_get_port);
|
||||
EXPORT_SYMBOL(tipc_get_handle);
|
||||
|
313
net/tipc/core.h
Normal file
313
net/tipc/core.h
Normal file
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* net/tipc/core.h: Include file for TIPC global declarations
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_CORE_H
|
||||
#define _TIPC_CORE_H
|
||||
|
||||
#include <net/tipc/tipc.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/hardirq.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
/*
|
||||
* TIPC debugging code
|
||||
*/
|
||||
|
||||
#define assert(i) BUG_ON(!(i))
|
||||
|
||||
struct tipc_msg;
|
||||
extern struct print_buf *CONS, *LOG;
|
||||
extern struct print_buf *TEE(struct print_buf *, struct print_buf *);
|
||||
void msg_print(struct print_buf*,struct tipc_msg *,const char*);
|
||||
void tipc_printf(struct print_buf *, const char *fmt, ...);
|
||||
void tipc_dump(struct print_buf*,const char *fmt, ...);
|
||||
|
||||
#ifdef CONFIG_TIPC_DEBUG
|
||||
|
||||
/*
|
||||
* TIPC debug support included:
|
||||
* - system messages are printed to TIPC_OUTPUT print buffer
|
||||
* - debug messages are printed to DBG_OUTPUT print buffer
|
||||
*/
|
||||
|
||||
#define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg)
|
||||
#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
|
||||
#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
|
||||
|
||||
#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
|
||||
#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) msg_print(DBG_OUTPUT, msg, txt);} while(0)
|
||||
#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
|
||||
|
||||
|
||||
/*
|
||||
* By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer,
|
||||
* while DBG_OUTPUT is the null print buffer. These defaults can be changed
|
||||
* here, or on a per .c file basis, by redefining these symbols. The following
|
||||
* print buffer options are available:
|
||||
*
|
||||
* NULL : Output to null print buffer (i.e. print nowhere)
|
||||
* CONS : Output to system console
|
||||
* LOG : Output to TIPC log buffer
|
||||
* &buf : Output to user-defined buffer (struct print_buf *)
|
||||
* TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TEE(CONS,LOG) )
|
||||
*/
|
||||
|
||||
#ifndef TIPC_OUTPUT
|
||||
#define TIPC_OUTPUT TEE(CONS,LOG)
|
||||
#endif
|
||||
|
||||
#ifndef DBG_OUTPUT
|
||||
#define DBG_OUTPUT NULL
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef DBG_OUTPUT
|
||||
#define DBG_OUTPUT NULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TIPC debug support not included:
|
||||
* - system messages are printed to system console
|
||||
* - debug messages are not printed
|
||||
*/
|
||||
|
||||
#define err(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __FILE__ , ## arg)
|
||||
#define info(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __FILE__ , ## arg)
|
||||
#define warn(fmt, arg...) printk(KERN_WARNING "%s: " fmt "\n" , __FILE__ , ## arg)
|
||||
|
||||
#define dbg(fmt, arg...) do {} while (0)
|
||||
#define msg_dbg(msg,txt) do {} while (0)
|
||||
#define dump(fmt,arg...) do {} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* TIPC-specific error codes
|
||||
*/
|
||||
|
||||
#define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */
|
||||
|
||||
/*
|
||||
* Global configuration variables
|
||||
*/
|
||||
|
||||
extern u32 tipc_own_addr;
|
||||
extern int tipc_max_zones;
|
||||
extern int tipc_max_clusters;
|
||||
extern int tipc_max_nodes;
|
||||
extern int tipc_max_slaves;
|
||||
extern int tipc_max_ports;
|
||||
extern int tipc_max_subscriptions;
|
||||
extern int tipc_max_publications;
|
||||
extern int tipc_net_id;
|
||||
extern int tipc_remote_management;
|
||||
|
||||
/*
|
||||
* Other global variables
|
||||
*/
|
||||
|
||||
extern int tipc_mode;
|
||||
extern int tipc_random;
|
||||
extern const char tipc_alphabet[];
|
||||
extern atomic_t tipc_user_count;
|
||||
|
||||
|
||||
/*
|
||||
* Routines available to privileged subsystems
|
||||
*/
|
||||
|
||||
extern int start_core(void);
|
||||
extern void stop_core(void);
|
||||
extern int start_net(void);
|
||||
extern void stop_net(void);
|
||||
|
||||
static inline int delimit(int val, int min, int max)
|
||||
{
|
||||
if (val > max)
|
||||
return max;
|
||||
if (val < min)
|
||||
return min;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TIPC timer and signal code
|
||||
*/
|
||||
|
||||
typedef void (*Handler) (unsigned long);
|
||||
|
||||
u32 k_signal(Handler routine, unsigned long argument);
|
||||
|
||||
/**
|
||||
* k_init_timer - initialize a timer
|
||||
* @timer: pointer to timer structure
|
||||
* @routine: pointer to routine to invoke when timer expires
|
||||
* @argument: value to pass to routine when timer expires
|
||||
*
|
||||
* Timer must be initialized before use (and terminated when no longer needed).
|
||||
*/
|
||||
|
||||
static inline void k_init_timer(struct timer_list *timer, Handler routine,
|
||||
unsigned long argument)
|
||||
{
|
||||
dbg("initializing timer %p\n", timer);
|
||||
init_timer(timer);
|
||||
timer->function = routine;
|
||||
timer->data = argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* k_start_timer - start a timer
|
||||
* @timer: pointer to timer structure
|
||||
* @msec: time to delay (in ms)
|
||||
*
|
||||
* Schedules a previously initialized timer for later execution.
|
||||
* If timer is already running, the new timeout overrides the previous request.
|
||||
*
|
||||
* To ensure the timer doesn't expire before the specified delay elapses,
|
||||
* the amount of delay is rounded up when converting to the jiffies
|
||||
* then an additional jiffy is added to account for the fact that
|
||||
* the starting time may be in the middle of the current jiffy.
|
||||
*/
|
||||
|
||||
static inline void k_start_timer(struct timer_list *timer, unsigned long msec)
|
||||
{
|
||||
dbg("starting timer %p for %u\n", timer, msec);
|
||||
mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* k_cancel_timer - cancel a timer
|
||||
* @timer: pointer to timer structure
|
||||
*
|
||||
* Cancels a previously initialized timer.
|
||||
* Can be called safely even if the timer is already inactive.
|
||||
*
|
||||
* WARNING: Must not be called when holding locks required by the timer's
|
||||
* timeout routine, otherwise deadlock can occur on SMP systems!
|
||||
*/
|
||||
|
||||
static inline void k_cancel_timer(struct timer_list *timer)
|
||||
{
|
||||
dbg("cancelling timer %p\n", timer);
|
||||
del_timer_sync(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* k_term_timer - terminate a timer
|
||||
* @timer: pointer to timer structure
|
||||
*
|
||||
* Prevents further use of a previously initialized timer.
|
||||
*
|
||||
* WARNING: Caller must ensure timer isn't currently running.
|
||||
*
|
||||
* (Do not "enhance" this routine to automatically cancel an active timer,
|
||||
* otherwise deadlock can arise when a timeout routine calls k_term_timer.)
|
||||
*/
|
||||
|
||||
static inline void k_term_timer(struct timer_list *timer)
|
||||
{
|
||||
dbg("terminating timer %p\n", timer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TIPC message buffer code
|
||||
*
|
||||
* TIPC message buffer headroom leaves room for 14 byte Ethernet header,
|
||||
* while ensuring TIPC header is word aligned for quicker access
|
||||
*/
|
||||
|
||||
#define BUF_HEADROOM 16u
|
||||
|
||||
struct tipc_skb_cb {
|
||||
void *handle;
|
||||
};
|
||||
|
||||
#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
|
||||
|
||||
|
||||
static inline struct tipc_msg *buf_msg(struct sk_buff *skb)
|
||||
{
|
||||
return (struct tipc_msg *)skb->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* buf_acquire - creates a TIPC message buffer
|
||||
* @size: message size (including TIPC header)
|
||||
*
|
||||
* Returns a new buffer. Space is reserved for a data link header.
|
||||
*/
|
||||
|
||||
static inline struct sk_buff *buf_acquire(u32 size)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
|
||||
|
||||
skb = alloc_skb(buf_size, GFP_ATOMIC);
|
||||
if (skb) {
|
||||
skb_reserve(skb, BUF_HEADROOM);
|
||||
skb_put(skb, size);
|
||||
skb->next = NULL;
|
||||
}
|
||||
return skb;
|
||||
}
|
||||
|
||||
/**
|
||||
* buf_discard - frees a TIPC message buffer
|
||||
* @skb: message buffer
|
||||
*
|
||||
* Frees a new buffer. If passed NULL, just returns.
|
||||
*/
|
||||
|
||||
static inline void buf_discard(struct sk_buff *skb)
|
||||
{
|
||||
if (likely(skb != NULL))
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
#endif
|
392
net/tipc/dbg.c
Normal file
392
net/tipc/dbg.c
Normal file
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* net/tipc/dbg.c: TIPC print buffer routines for debuggign
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "config.h"
|
||||
#include "dbg.h"
|
||||
|
||||
#define MAX_STRING 512
|
||||
|
||||
static char print_string[MAX_STRING];
|
||||
static spinlock_t print_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
|
||||
struct print_buf *CONS = &cons_buf;
|
||||
|
||||
static struct print_buf log_buf = { NULL, 0, NULL, NULL };
|
||||
struct print_buf *LOG = &log_buf;
|
||||
|
||||
|
||||
#define FORMAT(PTR,LEN,FMT) \
|
||||
{\
|
||||
va_list args;\
|
||||
va_start(args, FMT);\
|
||||
LEN = vsprintf(PTR, FMT, args);\
|
||||
va_end(args);\
|
||||
*(PTR + LEN) = '\0';\
|
||||
}
|
||||
|
||||
/*
|
||||
* Locking policy when using print buffers.
|
||||
*
|
||||
* 1) Routines of the form printbuf_XXX() rely on the caller to prevent
|
||||
* simultaneous use of the print buffer(s) being manipulated.
|
||||
* 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of
|
||||
* 'print_string' and to protect its print buffer(s).
|
||||
* 3) TEE() uses 'print_lock' to protect its print buffer(s).
|
||||
* 4) Routines of the form log_XXX() uses 'print_lock' to protect LOG.
|
||||
*/
|
||||
|
||||
/**
|
||||
* printbuf_init - initialize print buffer to empty
|
||||
*/
|
||||
|
||||
void printbuf_init(struct print_buf *pb, char *raw, u32 sz)
|
||||
{
|
||||
if (!pb || !raw || (sz < (MAX_STRING + 1)))
|
||||
return;
|
||||
|
||||
pb->crs = pb->buf = raw;
|
||||
pb->size = sz;
|
||||
pb->next = 0;
|
||||
pb->buf[0] = 0;
|
||||
pb->buf[sz-1] = ~0;
|
||||
}
|
||||
|
||||
/**
|
||||
* printbuf_reset - reinitialize print buffer to empty state
|
||||
*/
|
||||
|
||||
void printbuf_reset(struct print_buf *pb)
|
||||
{
|
||||
if (pb && pb->buf)
|
||||
printbuf_init(pb, pb->buf, pb->size);
|
||||
}
|
||||
|
||||
/**
|
||||
* printbuf_empty - test if print buffer is in empty state
|
||||
*/
|
||||
|
||||
int printbuf_empty(struct print_buf *pb)
|
||||
{
|
||||
return (!pb || !pb->buf || (pb->crs == pb->buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* printbuf_validate - check for print buffer overflow
|
||||
*
|
||||
* Verifies that a print buffer has captured all data written to it.
|
||||
* If data has been lost, linearize buffer and prepend an error message
|
||||
*
|
||||
* Returns length of print buffer data string (including trailing NULL)
|
||||
*/
|
||||
|
||||
int printbuf_validate(struct print_buf *pb)
|
||||
{
|
||||
char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n";
|
||||
char *cp_buf;
|
||||
struct print_buf cb;
|
||||
|
||||
if (!pb || !pb->buf)
|
||||
return 0;
|
||||
|
||||
if (pb->buf[pb->size - 1] == '\0') {
|
||||
cp_buf = kmalloc(pb->size, GFP_ATOMIC);
|
||||
if (cp_buf != NULL){
|
||||
printbuf_init(&cb, cp_buf, pb->size);
|
||||
printbuf_move(&cb, pb);
|
||||
printbuf_move(pb, &cb);
|
||||
kfree(cp_buf);
|
||||
memcpy(pb->buf, err, strlen(err));
|
||||
} else {
|
||||
printbuf_reset(pb);
|
||||
tipc_printf(pb, err);
|
||||
}
|
||||
}
|
||||
return (pb->crs - pb->buf + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* printbuf_move - move print buffer contents to another print buffer
|
||||
*
|
||||
* Current contents of destination print buffer (if any) are discarded.
|
||||
* Source print buffer becomes empty if a successful move occurs.
|
||||
*/
|
||||
|
||||
void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* Handle the cases where contents can't be moved */
|
||||
|
||||
if (!pb_to || !pb_to->buf)
|
||||
return;
|
||||
|
||||
if (!pb_from || !pb_from->buf) {
|
||||
printbuf_reset(pb_to);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pb_to->size < pb_from->size) {
|
||||
printbuf_reset(pb_to);
|
||||
tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy data from char after cursor to end (if used) */
|
||||
len = pb_from->buf + pb_from->size - pb_from->crs - 2;
|
||||
if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
|
||||
strcpy(pb_to->buf, pb_from->crs + 1);
|
||||
pb_to->crs = pb_to->buf + len;
|
||||
} else
|
||||
pb_to->crs = pb_to->buf;
|
||||
|
||||
/* Copy data from start to cursor (always) */
|
||||
len = pb_from->crs - pb_from->buf;
|
||||
strcpy(pb_to->crs, pb_from->buf);
|
||||
pb_to->crs += len;
|
||||
|
||||
printbuf_reset(pb_from);
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_printf - append formatted output to print buffer chain
|
||||
*/
|
||||
|
||||
void tipc_printf(struct print_buf *pb, const char *fmt, ...)
|
||||
{
|
||||
int chars_to_add;
|
||||
int chars_left;
|
||||
char save_char;
|
||||
struct print_buf *pb_next;
|
||||
|
||||
spin_lock_bh(&print_lock);
|
||||
FORMAT(print_string, chars_to_add, fmt);
|
||||
if (chars_to_add >= MAX_STRING)
|
||||
strcpy(print_string, "*** STRING TOO LONG ***");
|
||||
|
||||
while (pb) {
|
||||
if (pb == CONS)
|
||||
printk(print_string);
|
||||
else if (pb->buf) {
|
||||
chars_left = pb->buf + pb->size - pb->crs - 1;
|
||||
if (chars_to_add <= chars_left) {
|
||||
strcpy(pb->crs, print_string);
|
||||
pb->crs += chars_to_add;
|
||||
} else {
|
||||
strcpy(pb->buf, print_string + chars_left);
|
||||
save_char = print_string[chars_left];
|
||||
print_string[chars_left] = 0;
|
||||
strcpy(pb->crs, print_string);
|
||||
print_string[chars_left] = save_char;
|
||||
pb->crs = pb->buf + chars_to_add - chars_left;
|
||||
}
|
||||
}
|
||||
pb_next = pb->next;
|
||||
pb->next = 0;
|
||||
pb = pb_next;
|
||||
}
|
||||
spin_unlock_bh(&print_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* TEE - perform next output operation on both print buffers
|
||||
*/
|
||||
|
||||
struct print_buf *TEE(struct print_buf *b0, struct print_buf *b1)
|
||||
{
|
||||
struct print_buf *pb = b0;
|
||||
|
||||
if (!b0 || (b0 == b1))
|
||||
return b1;
|
||||
if (!b1)
|
||||
return b0;
|
||||
|
||||
spin_lock_bh(&print_lock);
|
||||
while (pb->next) {
|
||||
if ((pb->next == b1) || (pb->next == b0))
|
||||
pb->next = pb->next->next;
|
||||
else
|
||||
pb = pb->next;
|
||||
}
|
||||
pb->next = b1;
|
||||
spin_unlock_bh(&print_lock);
|
||||
return b0;
|
||||
}
|
||||
|
||||
/**
|
||||
* print_to_console - write string of bytes to console in multiple chunks
|
||||
*/
|
||||
|
||||
static void print_to_console(char *crs, int len)
|
||||
{
|
||||
int rest = len;
|
||||
|
||||
while (rest > 0) {
|
||||
int sz = rest < MAX_STRING ? rest : MAX_STRING;
|
||||
char c = crs[sz];
|
||||
|
||||
crs[sz] = 0;
|
||||
printk((const char *)crs);
|
||||
crs[sz] = c;
|
||||
rest -= sz;
|
||||
crs += sz;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* printbuf_dump - write print buffer contents to console
|
||||
*/
|
||||
|
||||
static void printbuf_dump(struct print_buf *pb)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* Dump print buffer from char after cursor to end (if used) */
|
||||
len = pb->buf + pb->size - pb->crs - 2;
|
||||
if ((pb->buf[pb->size - 1] == 0) && (len > 0))
|
||||
print_to_console(pb->crs + 1, len);
|
||||
|
||||
/* Dump print buffer from start to cursor (always) */
|
||||
len = pb->crs - pb->buf;
|
||||
print_to_console(pb->buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_dump - dump non-console print buffer(s) to console
|
||||
*/
|
||||
|
||||
void tipc_dump(struct print_buf *pb, const char *fmt, ...)
|
||||
{
|
||||
int len;
|
||||
|
||||
spin_lock_bh(&print_lock);
|
||||
FORMAT(CONS->buf, len, fmt);
|
||||
printk(CONS->buf);
|
||||
|
||||
for (; pb; pb = pb->next) {
|
||||
if (pb == CONS)
|
||||
continue;
|
||||
printk("\n---- Start of dump,%s log ----\n\n",
|
||||
(pb == LOG) ? "global" : "local");
|
||||
printbuf_dump(pb);
|
||||
printbuf_reset(pb);
|
||||
printk("\n-------- End of dump --------\n");
|
||||
}
|
||||
spin_unlock_bh(&print_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* log_stop - free up TIPC log print buffer
|
||||
*/
|
||||
|
||||
void log_stop(void)
|
||||
{
|
||||
spin_lock_bh(&print_lock);
|
||||
if (LOG->buf) {
|
||||
kfree(LOG->buf);
|
||||
LOG->buf = NULL;
|
||||
}
|
||||
spin_unlock_bh(&print_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* log_reinit - set TIPC log print buffer to specified size
|
||||
*/
|
||||
|
||||
void log_reinit(int log_size)
|
||||
{
|
||||
log_stop();
|
||||
|
||||
if (log_size) {
|
||||
if (log_size <= MAX_STRING)
|
||||
log_size = MAX_STRING + 1;
|
||||
spin_lock_bh(&print_lock);
|
||||
printbuf_init(LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
|
||||
spin_unlock_bh(&print_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* log_resize - reconfigure size of TIPC log buffer
|
||||
*/
|
||||
|
||||
struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
value = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
value = ntohl(value);
|
||||
if (value != delimit(value, 0, 32768))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (log size must be 0-32768)");
|
||||
log_reinit(value);
|
||||
return cfg_reply_none();
|
||||
}
|
||||
|
||||
/**
|
||||
* log_dump - capture TIPC log buffer contents in configuration message
|
||||
*/
|
||||
|
||||
struct sk_buff *log_dump(void)
|
||||
{
|
||||
struct sk_buff *reply;
|
||||
|
||||
spin_lock_bh(&print_lock);
|
||||
if (!LOG->buf)
|
||||
reply = cfg_reply_ultra_string("log not activated\n");
|
||||
else if (printbuf_empty(LOG))
|
||||
reply = cfg_reply_ultra_string("log is empty\n");
|
||||
else {
|
||||
struct tlv_desc *rep_tlv;
|
||||
struct print_buf pb;
|
||||
int str_len;
|
||||
|
||||
str_len = min(LOG->size, 32768u);
|
||||
reply = cfg_reply_alloc(TLV_SPACE(str_len));
|
||||
if (reply) {
|
||||
rep_tlv = (struct tlv_desc *)reply->data;
|
||||
printbuf_init(&pb, TLV_DATA(rep_tlv), str_len);
|
||||
printbuf_move(&pb, LOG);
|
||||
str_len = strlen(TLV_DATA(rep_tlv)) + 1;
|
||||
skb_put(reply, TLV_SPACE(str_len));
|
||||
TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&print_lock);
|
||||
return reply;
|
||||
}
|
||||
|
56
net/tipc/dbg.h
Normal file
56
net/tipc/dbg.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* net/tipc/dbg.h: Include file for TIPC print buffer routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_DBG_H
|
||||
#define _TIPC_DBG_H
|
||||
|
||||
struct print_buf {
|
||||
char *buf;
|
||||
u32 size;
|
||||
char *crs;
|
||||
struct print_buf *next;
|
||||
};
|
||||
|
||||
void printbuf_init(struct print_buf *pb, char *buf, u32 sz);
|
||||
void printbuf_reset(struct print_buf *pb);
|
||||
int printbuf_empty(struct print_buf *pb);
|
||||
int printbuf_validate(struct print_buf *pb);
|
||||
void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
|
||||
|
||||
void log_reinit(int log_size);
|
||||
void log_stop(void);
|
||||
|
||||
struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space);
|
||||
struct sk_buff *log_dump(void);
|
||||
|
||||
#endif
|
339
net/tipc/discover.c
Normal file
339
net/tipc/discover.c
Normal file
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* net/tipc/discover.c
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "dbg.h"
|
||||
#include "link.h"
|
||||
#include "zone.h"
|
||||
#include "discover.h"
|
||||
#include "port.h"
|
||||
#include "name_table.h"
|
||||
|
||||
#define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */
|
||||
#define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */
|
||||
#define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */
|
||||
|
||||
#if 0
|
||||
#define GET_NODE_INFO 300
|
||||
#define GET_NODE_INFO_RESULT 301
|
||||
#define FORWARD_LINK_PROBE 302
|
||||
#define LINK_REQUEST_REJECTED 303
|
||||
#define LINK_REQUEST_ACCEPTED 304
|
||||
#define DROP_LINK_REQUEST 305
|
||||
#define CHECK_LINK_COUNT 306
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO: Most of the inter-cluster setup stuff should be
|
||||
* rewritten, and be made conformant with specification.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* struct link_req - information about an ongoing link setup request
|
||||
* @bearer: bearer issuing requests
|
||||
* @dest: destination address for request messages
|
||||
* @buf: request message to be (repeatedly) sent
|
||||
* @timer: timer governing period between requests
|
||||
* @timer_intv: current interval between requests (in ms)
|
||||
*/
|
||||
struct link_req {
|
||||
struct bearer *bearer;
|
||||
struct tipc_media_addr dest;
|
||||
struct sk_buff *buf;
|
||||
struct timer_list timer;
|
||||
unsigned int timer_intv;
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
int disc_create_link(const struct tipc_link_create *argv)
|
||||
{
|
||||
/*
|
||||
* Code for inter cluster link setup here
|
||||
*/
|
||||
return TIPC_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* disc_lost_link(): A link has lost contact
|
||||
*/
|
||||
|
||||
void disc_link_event(u32 addr, char *name, int up)
|
||||
{
|
||||
if (in_own_cluster(addr))
|
||||
return;
|
||||
/*
|
||||
* Code for inter cluster link setup here
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* disc_init_msg - initialize a link setup message
|
||||
* @type: message type (request or response)
|
||||
* @req_links: number of links associated with message
|
||||
* @dest_domain: network domain of node(s) which should respond to message
|
||||
* @b_ptr: ptr to bearer issuing message
|
||||
*/
|
||||
|
||||
struct sk_buff *disc_init_msg(u32 type,
|
||||
u32 req_links,
|
||||
u32 dest_domain,
|
||||
struct bearer *b_ptr)
|
||||
{
|
||||
struct sk_buff *buf = buf_acquire(DSC_H_SIZE);
|
||||
struct tipc_msg *msg;
|
||||
|
||||
if (buf) {
|
||||
msg = buf_msg(buf);
|
||||
msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE,
|
||||
dest_domain);
|
||||
msg_set_non_seq(msg);
|
||||
msg_set_req_links(msg, req_links);
|
||||
msg_set_dest_domain(msg, dest_domain);
|
||||
msg_set_bc_netid(msg, tipc_net_id);
|
||||
msg_set_media_addr(msg, &b_ptr->publ.addr);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* disc_recv_msg - handle incoming link setup message (request or response)
|
||||
* @buf: buffer containing message
|
||||
*/
|
||||
|
||||
void disc_recv_msg(struct sk_buff *buf)
|
||||
{
|
||||
struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle;
|
||||
struct link *link;
|
||||
struct tipc_media_addr media_addr;
|
||||
struct tipc_msg *msg = buf_msg(buf);
|
||||
u32 dest = msg_dest_domain(msg);
|
||||
u32 orig = msg_prevnode(msg);
|
||||
u32 net_id = msg_bc_netid(msg);
|
||||
u32 type = msg_type(msg);
|
||||
|
||||
msg_get_media_addr(msg,&media_addr);
|
||||
msg_dbg(msg, "RECV:");
|
||||
buf_discard(buf);
|
||||
|
||||
if (net_id != tipc_net_id)
|
||||
return;
|
||||
if (!addr_domain_valid(dest))
|
||||
return;
|
||||
if (!addr_node_valid(orig))
|
||||
return;
|
||||
if (orig == tipc_own_addr)
|
||||
return;
|
||||
if (!in_scope(dest, tipc_own_addr))
|
||||
return;
|
||||
if (is_slave(tipc_own_addr) && is_slave(orig))
|
||||
return;
|
||||
if (is_slave(orig) && !in_own_cluster(orig))
|
||||
return;
|
||||
if (in_own_cluster(orig)) {
|
||||
/* Always accept link here */
|
||||
struct sk_buff *rbuf;
|
||||
struct tipc_media_addr *addr;
|
||||
struct node *n_ptr = node_find(orig);
|
||||
int link_up;
|
||||
dbg(" in own cluster\n");
|
||||
if (n_ptr == NULL) {
|
||||
n_ptr = node_create(orig);
|
||||
}
|
||||
if (n_ptr == NULL) {
|
||||
warn("Memory squeeze; Failed to create node\n");
|
||||
return;
|
||||
}
|
||||
spin_lock_bh(&n_ptr->lock);
|
||||
link = n_ptr->links[b_ptr->identity];
|
||||
if (!link) {
|
||||
dbg("creating link\n");
|
||||
link = link_create(b_ptr, orig, &media_addr);
|
||||
if (!link) {
|
||||
spin_unlock_bh(&n_ptr->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
addr = &link->media_addr;
|
||||
if (memcmp(addr, &media_addr, sizeof(*addr))) {
|
||||
char addr_string[16];
|
||||
|
||||
warn("New bearer address for %s\n",
|
||||
addr_string_fill(addr_string, orig));
|
||||
memcpy(addr, &media_addr, sizeof(*addr));
|
||||
link_reset(link);
|
||||
}
|
||||
link_up = link_is_up(link);
|
||||
spin_unlock_bh(&n_ptr->lock);
|
||||
if ((type == DSC_RESP_MSG) || link_up)
|
||||
return;
|
||||
rbuf = disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
|
||||
if (rbuf != NULL) {
|
||||
msg_dbg(buf_msg(rbuf),"SEND:");
|
||||
b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr);
|
||||
buf_discard(rbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* disc_stop_link_req - stop sending periodic link setup requests
|
||||
* @req: ptr to link request structure
|
||||
*/
|
||||
|
||||
void disc_stop_link_req(struct link_req *req)
|
||||
{
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
k_cancel_timer(&req->timer);
|
||||
k_term_timer(&req->timer);
|
||||
buf_discard(req->buf);
|
||||
kfree(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* disc_update_link_req - update frequency of periodic link setup requests
|
||||
* @req: ptr to link request structure
|
||||
*/
|
||||
|
||||
void disc_update_link_req(struct link_req *req)
|
||||
{
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
if (req->timer_intv == TIPC_LINK_REQ_SLOW) {
|
||||
if (!req->bearer->nodes.count) {
|
||||
req->timer_intv = TIPC_LINK_REQ_FAST;
|
||||
k_start_timer(&req->timer, req->timer_intv);
|
||||
}
|
||||
} else if (req->timer_intv == TIPC_LINK_REQ_FAST) {
|
||||
if (req->bearer->nodes.count) {
|
||||
req->timer_intv = TIPC_LINK_REQ_SLOW;
|
||||
k_start_timer(&req->timer, req->timer_intv);
|
||||
}
|
||||
} else {
|
||||
/* leave timer "as is" if haven't yet reached a "normal" rate */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* disc_timeout - send a periodic link setup request
|
||||
* @req: ptr to link request structure
|
||||
*
|
||||
* Called whenever a link setup request timer associated with a bearer expires.
|
||||
*/
|
||||
|
||||
static void disc_timeout(struct link_req *req)
|
||||
{
|
||||
struct tipc_msg *msg = buf_msg(req->buf);
|
||||
|
||||
spin_lock_bh(&req->bearer->publ.lock);
|
||||
|
||||
#if 0
|
||||
/* CURRENTLY DON'T SUPPORT INTER-ZONE LINKS */
|
||||
u32 dest_domain = msg_dest_domain(msg);
|
||||
int stop = 0;
|
||||
if (!in_scope(dest_domain, tipc_own_addr)) {
|
||||
struct _zone *z_ptr = zone_find(dest_domain);
|
||||
|
||||
if (z_ptr && (z_ptr->links >= msg_req_links(msg)))
|
||||
stop = 1;
|
||||
if (req->timer_intv >= 32000)
|
||||
stop = 1;
|
||||
}
|
||||
if (stop) {
|
||||
k_cancel_timer(&req->timer);
|
||||
buf_discard(req->buf);
|
||||
kfree(req);
|
||||
spin_unlock_bh(&req->bearer->publ.lock);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
msg_dbg(msg,"SEND:");
|
||||
req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest);
|
||||
|
||||
if ((req->timer_intv == TIPC_LINK_REQ_SLOW) ||
|
||||
(req->timer_intv == TIPC_LINK_REQ_FAST)) {
|
||||
/* leave timer interval "as is" if already at a "normal" rate */
|
||||
} else {
|
||||
req->timer_intv *= 2;
|
||||
if (req->timer_intv > TIPC_LINK_REQ_FAST)
|
||||
req->timer_intv = TIPC_LINK_REQ_FAST;
|
||||
if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
|
||||
(req->bearer->nodes.count))
|
||||
req->timer_intv = TIPC_LINK_REQ_SLOW;
|
||||
}
|
||||
k_start_timer(&req->timer, req->timer_intv);
|
||||
|
||||
spin_unlock_bh(&req->bearer->publ.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* disc_init_link_req - start sending periodic link setup requests
|
||||
* @b_ptr: ptr to bearer issuing requests
|
||||
* @dest: destination address for request messages
|
||||
* @dest_domain: network domain of node(s) which should respond to message
|
||||
* @req_links: max number of desired links
|
||||
*
|
||||
* Returns pointer to link request structure, or NULL if unable to create.
|
||||
*/
|
||||
|
||||
struct link_req *disc_init_link_req(struct bearer *b_ptr,
|
||||
const struct tipc_media_addr *dest,
|
||||
u32 dest_domain,
|
||||
u32 req_links)
|
||||
{
|
||||
struct link_req *req;
|
||||
|
||||
req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC);
|
||||
if (!req)
|
||||
return NULL;
|
||||
|
||||
req->buf = disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr);
|
||||
if (!req->buf) {
|
||||
kfree(req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(&req->dest, dest, sizeof(*dest));
|
||||
req->bearer = b_ptr;
|
||||
req->timer_intv = TIPC_LINK_REQ_INIT;
|
||||
k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
|
||||
k_start_timer(&req->timer, req->timer_intv);
|
||||
return req;
|
||||
}
|
||||
|
55
net/tipc/discover.h
Normal file
55
net/tipc/discover.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* net/tipc/discover.h
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_DISCOVER_H
|
||||
#define _TIPC_DISCOVER_H
|
||||
|
||||
#include <linux/tipc.h>
|
||||
|
||||
struct link_req;
|
||||
|
||||
struct link_req *disc_init_link_req(struct bearer *b_ptr,
|
||||
const struct tipc_media_addr *dest,
|
||||
u32 dest_domain,
|
||||
u32 req_links);
|
||||
void disc_update_link_req(struct link_req *req);
|
||||
void disc_stop_link_req(struct link_req *req);
|
||||
|
||||
void disc_recv_msg(struct sk_buff *buf);
|
||||
|
||||
void disc_link_event(u32 addr, char *name, int up);
|
||||
#if 0
|
||||
int disc_create_link(const struct tipc_link_create *argv);
|
||||
#endif
|
||||
|
||||
#endif
|
296
net/tipc/eth_media.c
Normal file
296
net/tipc/eth_media.c
Normal file
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* net/tipc/eth_media.c: Ethernet bearer support for TIPC
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <net/tipc/tipc.h>
|
||||
#include <net/tipc/tipc_bearer.h>
|
||||
#include <net/tipc/tipc_msg.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#define MAX_ETH_BEARERS 2
|
||||
#define TIPC_PROTOCOL 0x88ca
|
||||
#define ETH_LINK_PRIORITY 10
|
||||
#define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL
|
||||
|
||||
|
||||
/**
|
||||
* struct eth_bearer - Ethernet bearer data structure
|
||||
* @bearer: ptr to associated "generic" bearer structure
|
||||
* @dev: ptr to associated Ethernet network device
|
||||
* @tipc_packet_type: used in binding TIPC to Ethernet driver
|
||||
*/
|
||||
|
||||
struct eth_bearer {
|
||||
struct tipc_bearer *bearer;
|
||||
struct net_device *dev;
|
||||
struct packet_type tipc_packet_type;
|
||||
};
|
||||
|
||||
static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
|
||||
static int eth_started = 0;
|
||||
static struct notifier_block notifier;
|
||||
|
||||
/**
|
||||
* send_msg - send a TIPC message out over an Ethernet interface
|
||||
*/
|
||||
|
||||
static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *dest)
|
||||
{
|
||||
struct sk_buff *clone;
|
||||
struct net_device *dev;
|
||||
|
||||
clone = skb_clone(buf, GFP_ATOMIC);
|
||||
if (clone) {
|
||||
clone->nh.raw = clone->data;
|
||||
dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
|
||||
clone->dev = dev;
|
||||
dev->hard_header(clone, dev, TIPC_PROTOCOL,
|
||||
&dest->dev_addr.eth_addr,
|
||||
dev->dev_addr, clone->len);
|
||||
dev_queue_xmit(clone);
|
||||
}
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* recv_msg - handle incoming TIPC message from an Ethernet interface
|
||||
*
|
||||
* Routine truncates any Ethernet padding/CRC appended to the message,
|
||||
* and ensures message size matches actual length
|
||||
*/
|
||||
|
||||
static int recv_msg(struct sk_buff *buf, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *orig_dev)
|
||||
{
|
||||
struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
|
||||
u32 size;
|
||||
|
||||
if (likely(eb_ptr->bearer)) {
|
||||
size = msg_size((struct tipc_msg *)buf->data);
|
||||
skb_trim(buf, size);
|
||||
if (likely(buf->len == size)) {
|
||||
buf->next = NULL;
|
||||
tipc_recv_msg(buf, eb_ptr->bearer);
|
||||
} else {
|
||||
kfree_skb(buf);
|
||||
}
|
||||
} else {
|
||||
kfree_skb(buf);
|
||||
}
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_bearer - attach TIPC bearer to an Ethernet interface
|
||||
*/
|
||||
|
||||
static int enable_bearer(struct tipc_bearer *tb_ptr)
|
||||
{
|
||||
struct net_device *dev = dev_base;
|
||||
struct eth_bearer *eb_ptr = ð_bearers[0];
|
||||
struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS];
|
||||
char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
|
||||
|
||||
/* Find device with specified name */
|
||||
|
||||
while (dev && dev->name &&
|
||||
(memcmp(dev->name, driver_name, strlen(dev->name)))) {
|
||||
dev = dev->next;
|
||||
}
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Find Ethernet bearer for device (or create one) */
|
||||
|
||||
for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++);
|
||||
if (eb_ptr == stop)
|
||||
return -EDQUOT;
|
||||
if (!eb_ptr->dev) {
|
||||
eb_ptr->dev = dev;
|
||||
eb_ptr->tipc_packet_type.type = __constant_htons(TIPC_PROTOCOL);
|
||||
eb_ptr->tipc_packet_type.dev = dev;
|
||||
eb_ptr->tipc_packet_type.func = recv_msg;
|
||||
eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
|
||||
INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
|
||||
dev_hold(dev);
|
||||
dev_add_pack(&eb_ptr->tipc_packet_type);
|
||||
}
|
||||
|
||||
/* Associate TIPC bearer with Ethernet bearer */
|
||||
|
||||
eb_ptr->bearer = tb_ptr;
|
||||
tb_ptr->usr_handle = (void *)eb_ptr;
|
||||
tb_ptr->mtu = dev->mtu;
|
||||
tb_ptr->blocked = 0;
|
||||
tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
|
||||
memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_bearer - detach TIPC bearer from an Ethernet interface
|
||||
*
|
||||
* We really should do dev_remove_pack() here, but this function can not be
|
||||
* called at tasklet level. => Use eth_bearer->bearer as a flag to throw away
|
||||
* incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit.
|
||||
*/
|
||||
|
||||
static void disable_bearer(struct tipc_bearer *tb_ptr)
|
||||
{
|
||||
((struct eth_bearer *)tb_ptr->usr_handle)->bearer = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* recv_notification - handle device updates from OS
|
||||
*
|
||||
* Change the state of the Ethernet bearer (if any) associated with the
|
||||
* specified device.
|
||||
*/
|
||||
|
||||
static int recv_notification(struct notifier_block *nb, unsigned long evt,
|
||||
void *dv)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)dv;
|
||||
struct eth_bearer *eb_ptr = ð_bearers[0];
|
||||
struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS];
|
||||
|
||||
while ((eb_ptr->dev != dev)) {
|
||||
if (++eb_ptr == stop)
|
||||
return NOTIFY_DONE; /* couldn't find device */
|
||||
}
|
||||
if (!eb_ptr->bearer)
|
||||
return NOTIFY_DONE; /* bearer had been disabled */
|
||||
|
||||
eb_ptr->bearer->mtu = dev->mtu;
|
||||
|
||||
switch (evt) {
|
||||
case NETDEV_CHANGE:
|
||||
if (netif_carrier_ok(dev))
|
||||
tipc_continue(eb_ptr->bearer);
|
||||
else
|
||||
tipc_block_bearer(eb_ptr->bearer->name);
|
||||
break;
|
||||
case NETDEV_UP:
|
||||
tipc_continue(eb_ptr->bearer);
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
tipc_block_bearer(eb_ptr->bearer->name);
|
||||
break;
|
||||
case NETDEV_CHANGEMTU:
|
||||
case NETDEV_CHANGEADDR:
|
||||
tipc_block_bearer(eb_ptr->bearer->name);
|
||||
tipc_continue(eb_ptr->bearer);
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
case NETDEV_CHANGENAME:
|
||||
tipc_disable_bearer(eb_ptr->bearer->name);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_addr2str - convert Ethernet address to string
|
||||
*/
|
||||
|
||||
static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
|
||||
{
|
||||
unchar *addr = (unchar *)&a->dev_addr;
|
||||
|
||||
if (str_size < 18)
|
||||
*str_buf = '\0';
|
||||
else
|
||||
sprintf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
return str_buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_media_start - activate Ethernet bearer support
|
||||
*
|
||||
* Register Ethernet media type with TIPC bearer code. Also register
|
||||
* with OS for notifications about device state changes.
|
||||
*/
|
||||
|
||||
int eth_media_start(void)
|
||||
{
|
||||
struct tipc_media_addr bcast_addr;
|
||||
int res;
|
||||
|
||||
if (eth_started)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&bcast_addr, 0xff, sizeof(bcast_addr));
|
||||
memset(eth_bearers, 0, sizeof(eth_bearers));
|
||||
|
||||
res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
|
||||
enable_bearer, disable_bearer, send_msg,
|
||||
eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY,
|
||||
ETH_LINK_TOLERANCE, TIPC_DEF_LINK_WIN);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
notifier.notifier_call = &recv_notification;
|
||||
notifier.priority = 0;
|
||||
res = register_netdevice_notifier(¬ifier);
|
||||
if (!res)
|
||||
eth_started = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_media_stop - deactivate Ethernet bearer support
|
||||
*/
|
||||
|
||||
void eth_media_stop(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!eth_started)
|
||||
return;
|
||||
|
||||
unregister_netdevice_notifier(¬ifier);
|
||||
for (i = 0; i < MAX_ETH_BEARERS ; i++) {
|
||||
if (eth_bearers[i].bearer) {
|
||||
eth_bearers[i].bearer->blocked = 1;
|
||||
eth_bearers[i].bearer = 0;
|
||||
}
|
||||
if (eth_bearers[i].dev) {
|
||||
dev_remove_pack(ð_bearers[i].tipc_packet_type);
|
||||
dev_put(eth_bearers[i].dev);
|
||||
}
|
||||
}
|
||||
memset(ð_bearers, 0, sizeof(eth_bearers));
|
||||
eth_started = 0;
|
||||
}
|
129
net/tipc/handler.c
Normal file
129
net/tipc/handler.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* net/tipc/handler.c: TIPC signal handling
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
struct queue_item {
|
||||
struct list_head next_signal;
|
||||
void (*handler) (unsigned long);
|
||||
unsigned long data;
|
||||
};
|
||||
|
||||
static kmem_cache_t *tipc_queue_item_cache;
|
||||
static struct list_head signal_queue_head;
|
||||
static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED;
|
||||
static int handler_enabled = 0;
|
||||
|
||||
static void process_signal_queue(unsigned long dummy);
|
||||
|
||||
static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0);
|
||||
|
||||
|
||||
unsigned int k_signal(Handler routine, unsigned long argument)
|
||||
{
|
||||
struct queue_item *item;
|
||||
|
||||
if (!handler_enabled) {
|
||||
err("Signal request ignored by handler\n");
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
|
||||
spin_lock_bh(&qitem_lock);
|
||||
item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC);
|
||||
if (!item) {
|
||||
err("Signal queue out of memory\n");
|
||||
spin_unlock_bh(&qitem_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
item->handler = routine;
|
||||
item->data = argument;
|
||||
list_add_tail(&item->next_signal, &signal_queue_head);
|
||||
spin_unlock_bh(&qitem_lock);
|
||||
tasklet_schedule(&tipc_tasklet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void process_signal_queue(unsigned long dummy)
|
||||
{
|
||||
struct queue_item *__volatile__ item;
|
||||
struct list_head *l, *n;
|
||||
|
||||
spin_lock_bh(&qitem_lock);
|
||||
list_for_each_safe(l, n, &signal_queue_head) {
|
||||
item = list_entry(l, struct queue_item, next_signal);
|
||||
list_del(&item->next_signal);
|
||||
spin_unlock_bh(&qitem_lock);
|
||||
item->handler(item->data);
|
||||
spin_lock_bh(&qitem_lock);
|
||||
kmem_cache_free(tipc_queue_item_cache, item);
|
||||
}
|
||||
spin_unlock_bh(&qitem_lock);
|
||||
}
|
||||
|
||||
int handler_start(void)
|
||||
{
|
||||
tipc_queue_item_cache =
|
||||
kmem_cache_create("tipc_queue_items", sizeof(struct queue_item),
|
||||
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
|
||||
if (!tipc_queue_item_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&signal_queue_head);
|
||||
tasklet_enable(&tipc_tasklet);
|
||||
handler_enabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handler_stop(void)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
struct queue_item *item;
|
||||
|
||||
if (!handler_enabled)
|
||||
return;
|
||||
|
||||
handler_enabled = 0;
|
||||
tasklet_disable(&tipc_tasklet);
|
||||
tasklet_kill(&tipc_tasklet);
|
||||
|
||||
spin_lock_bh(&qitem_lock);
|
||||
list_for_each_safe(l, n, &signal_queue_head) {
|
||||
item = list_entry(l, struct queue_item, next_signal);
|
||||
list_del(&item->next_signal);
|
||||
kmem_cache_free(tipc_queue_item_cache, item);
|
||||
}
|
||||
spin_unlock_bh(&qitem_lock);
|
||||
|
||||
kmem_cache_destroy(tipc_queue_item_cache);
|
||||
}
|
||||
|
3164
net/tipc/link.c
Normal file
3164
net/tipc/link.c
Normal file
File diff suppressed because it is too large
Load diff
293
net/tipc/link.h
Normal file
293
net/tipc/link.h
Normal file
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* net/tipc/link.h: Include file for TIPC link code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_LINK_H
|
||||
#define _TIPC_LINK_H
|
||||
|
||||
#include "dbg.h"
|
||||
#include "msg.h"
|
||||
#include "bearer.h"
|
||||
#include "node.h"
|
||||
|
||||
#define PUSH_FAILED 1
|
||||
#define PUSH_FINISHED 2
|
||||
|
||||
/*
|
||||
* Link states
|
||||
*/
|
||||
|
||||
#define WORKING_WORKING 560810u
|
||||
#define WORKING_UNKNOWN 560811u
|
||||
#define RESET_UNKNOWN 560812u
|
||||
#define RESET_RESET 560813u
|
||||
|
||||
/*
|
||||
* Starting value for maximum packet size negotiation on unicast links
|
||||
* (unless bearer MTU is less)
|
||||
*/
|
||||
|
||||
#define MAX_PKT_DEFAULT 1500
|
||||
|
||||
/**
|
||||
* struct link - TIPC link data structure
|
||||
* @addr: network address of link's peer node
|
||||
* @name: link name character string
|
||||
* @media_addr: media address to use when sending messages over link
|
||||
* @timer: link timer
|
||||
* @owner: pointer to peer node
|
||||
* @link_list: adjacent links in bearer's list of links
|
||||
* @started: indicates if link has been started
|
||||
* @checkpoint: reference point for triggering link continuity checking
|
||||
* @peer_session: link session # being used by peer end of link
|
||||
* @peer_bearer_id: bearer id used by link's peer endpoint
|
||||
* @b_ptr: pointer to bearer used by link
|
||||
* @tolerance: minimum link continuity loss needed to reset link [in ms]
|
||||
* @continuity_interval: link continuity testing interval [in ms]
|
||||
* @abort_limit: # of unacknowledged continuity probes needed to reset link
|
||||
* @state: current state of link FSM
|
||||
* @blocked: indicates if link has been administratively blocked
|
||||
* @fsm_msg_cnt: # of protocol messages link FSM has sent in current state
|
||||
* @proto_msg: template for control messages generated by link
|
||||
* @pmsg: convenience pointer to "proto_msg" field
|
||||
* @priority: current link priority
|
||||
* @queue_limit: outbound message queue congestion thresholds (indexed by user)
|
||||
* @exp_msg_count: # of tunnelled messages expected during link changeover
|
||||
* @reset_checkpoint: seq # of last acknowledged message at time of link reset
|
||||
* @max_pkt: current maximum packet size for this link
|
||||
* @max_pkt_target: desired maximum packet size for this link
|
||||
* @max_pkt_probes: # of probes based on current (max_pkt, max_pkt_target)
|
||||
* @out_queue_size: # of messages in outbound message queue
|
||||
* @first_out: ptr to first outbound message in queue
|
||||
* @last_out: ptr to last outbound message in queue
|
||||
* @next_out_no: next sequence number to use for outbound messages
|
||||
* @last_retransmitted: sequence number of most recently retransmitted message
|
||||
* @stale_count: # of identical retransmit requests made by peer
|
||||
* @next_in_no: next sequence number to expect for inbound messages
|
||||
* @deferred_inqueue_sz: # of messages in inbound message queue
|
||||
* @oldest_deferred_in: ptr to first inbound message in queue
|
||||
* @newest_deferred_in: ptr to last inbound message in queue
|
||||
* @unacked_window: # of inbound messages rx'd without ack'ing back to peer
|
||||
* @proto_msg_queue: ptr to (single) outbound control message
|
||||
* @retransm_queue_size: number of messages to retransmit
|
||||
* @retransm_queue_head: sequence number of first message to retransmit
|
||||
* @next_out: ptr to first unsent outbound message in queue
|
||||
* @waiting_ports: linked list of ports waiting for link congestion to abate
|
||||
* @long_msg_seq_no: next identifier to use for outbound fragmented messages
|
||||
* @defragm_buf: list of partially reassembled inbound message fragments
|
||||
* @stats: collects statistics regarding link activity
|
||||
* @print_buf: print buffer used to log link activity
|
||||
*/
|
||||
|
||||
struct link {
|
||||
u32 addr;
|
||||
char name[TIPC_MAX_LINK_NAME];
|
||||
struct tipc_media_addr media_addr;
|
||||
struct timer_list timer;
|
||||
struct node *owner;
|
||||
struct list_head link_list;
|
||||
|
||||
/* Management and link supervision data */
|
||||
int started;
|
||||
u32 checkpoint;
|
||||
u32 peer_session;
|
||||
u32 peer_bearer_id;
|
||||
struct bearer *b_ptr;
|
||||
u32 tolerance;
|
||||
u32 continuity_interval;
|
||||
u32 abort_limit;
|
||||
int state;
|
||||
int blocked;
|
||||
u32 fsm_msg_cnt;
|
||||
struct {
|
||||
unchar hdr[INT_H_SIZE];
|
||||
unchar body[TIPC_MAX_IF_NAME];
|
||||
} proto_msg;
|
||||
struct tipc_msg *pmsg;
|
||||
u32 priority;
|
||||
u32 queue_limit[15]; /* queue_limit[0]==window limit */
|
||||
|
||||
/* Changeover */
|
||||
u32 exp_msg_count;
|
||||
u32 reset_checkpoint;
|
||||
|
||||
/* Max packet negotiation */
|
||||
u32 max_pkt;
|
||||
u32 max_pkt_target;
|
||||
u32 max_pkt_probes;
|
||||
|
||||
/* Sending */
|
||||
u32 out_queue_size;
|
||||
struct sk_buff *first_out;
|
||||
struct sk_buff *last_out;
|
||||
u32 next_out_no;
|
||||
u32 last_retransmitted;
|
||||
u32 stale_count;
|
||||
|
||||
/* Reception */
|
||||
u32 next_in_no;
|
||||
u32 deferred_inqueue_sz;
|
||||
struct sk_buff *oldest_deferred_in;
|
||||
struct sk_buff *newest_deferred_in;
|
||||
u32 unacked_window;
|
||||
|
||||
/* Congestion handling */
|
||||
struct sk_buff *proto_msg_queue;
|
||||
u32 retransm_queue_size;
|
||||
u32 retransm_queue_head;
|
||||
struct sk_buff *next_out;
|
||||
struct list_head waiting_ports;
|
||||
|
||||
/* Fragmentation/defragmentation */
|
||||
u32 long_msg_seq_no;
|
||||
struct sk_buff *defragm_buf;
|
||||
|
||||
/* Statistics */
|
||||
struct {
|
||||
u32 sent_info; /* used in counting # sent packets */
|
||||
u32 recv_info; /* used in counting # recv'd packets */
|
||||
u32 sent_states;
|
||||
u32 recv_states;
|
||||
u32 sent_probes;
|
||||
u32 recv_probes;
|
||||
u32 sent_nacks;
|
||||
u32 recv_nacks;
|
||||
u32 sent_acks;
|
||||
u32 sent_bundled;
|
||||
u32 sent_bundles;
|
||||
u32 recv_bundled;
|
||||
u32 recv_bundles;
|
||||
u32 retransmitted;
|
||||
u32 sent_fragmented;
|
||||
u32 sent_fragments;
|
||||
u32 recv_fragmented;
|
||||
u32 recv_fragments;
|
||||
u32 link_congs; /* # port sends blocked by congestion */
|
||||
u32 bearer_congs;
|
||||
u32 deferred_recv;
|
||||
u32 duplicates;
|
||||
|
||||
/* for statistical profiling of send queue size */
|
||||
|
||||
u32 max_queue_sz;
|
||||
u32 accu_queue_sz;
|
||||
u32 queue_sz_counts;
|
||||
|
||||
/* for statistical profiling of message lengths */
|
||||
|
||||
u32 msg_length_counts;
|
||||
u32 msg_lengths_total;
|
||||
u32 msg_length_profile[7];
|
||||
#if 0
|
||||
u32 sent_tunneled;
|
||||
u32 recv_tunneled;
|
||||
#endif
|
||||
} stats;
|
||||
|
||||
struct print_buf print_buf;
|
||||
};
|
||||
|
||||
struct port;
|
||||
|
||||
struct link *link_create(struct bearer *b_ptr, const u32 peer,
|
||||
const struct tipc_media_addr *media_addr);
|
||||
void link_delete(struct link *l_ptr);
|
||||
void link_changeover(struct link *l_ptr);
|
||||
void link_send_duplicate(struct link *l_ptr, struct link *dest);
|
||||
void link_reset_fragments(struct link *l_ptr);
|
||||
int link_is_up(struct link *l_ptr);
|
||||
int link_is_active(struct link *l_ptr);
|
||||
void link_start(struct link *l_ptr);
|
||||
u32 link_push_packet(struct link *l_ptr);
|
||||
void link_stop(struct link *l_ptr);
|
||||
struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
|
||||
struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
|
||||
struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
|
||||
void link_reset(struct link *l_ptr);
|
||||
int link_send(struct sk_buff *buf, u32 dest, u32 selector);
|
||||
int link_send_buf(struct link *l_ptr, struct sk_buff *buf);
|
||||
u32 link_get_max_pkt(u32 dest,u32 selector);
|
||||
int link_send_sections_fast(struct port* sender,
|
||||
struct iovec const *msg_sect,
|
||||
const u32 num_sect,
|
||||
u32 destnode);
|
||||
|
||||
int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
|
||||
void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
|
||||
struct tipc_msg *msg, u32 selector);
|
||||
void link_recv_bundle(struct sk_buff *buf);
|
||||
int link_recv_fragment(struct sk_buff **pending,
|
||||
struct sk_buff **fb,
|
||||
struct tipc_msg **msg);
|
||||
void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap,
|
||||
u32 tolerance, u32 priority, u32 acked_mtu);
|
||||
void link_push_queue(struct link *l_ptr);
|
||||
u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
|
||||
struct sk_buff *buf);
|
||||
void link_wakeup_ports(struct link *l_ptr, int all);
|
||||
void link_set_queue_limits(struct link *l_ptr, u32 window);
|
||||
void link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits);
|
||||
|
||||
/*
|
||||
* Link sequence number manipulation routines (uses modulo 2**16 arithmetic)
|
||||
*/
|
||||
|
||||
static inline u32 mod(u32 x)
|
||||
{
|
||||
return x & 0xffffu;
|
||||
}
|
||||
|
||||
static inline int between(u32 lower, u32 upper, u32 n)
|
||||
{
|
||||
if ((lower < n) && (n < upper))
|
||||
return 1;
|
||||
if ((upper < lower) && ((n > lower) || (n < upper)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int less_eq(u32 left, u32 right)
|
||||
{
|
||||
return (mod(right - left) < 32768u);
|
||||
}
|
||||
|
||||
static inline int less(u32 left, u32 right)
|
||||
{
|
||||
return (less_eq(left, right) && (mod(right) != mod(left)));
|
||||
}
|
||||
|
||||
static inline u32 lesser(u32 left, u32 right)
|
||||
{
|
||||
return less_eq(left, right) ? left : right;
|
||||
}
|
||||
|
||||
#endif
|
331
net/tipc/msg.c
Normal file
331
net/tipc/msg.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* net/tipc/msg.c: TIPC message header routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "addr.h"
|
||||
#include "dbg.h"
|
||||
#include "msg.h"
|
||||
#include "bearer.h"
|
||||
|
||||
|
||||
void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
|
||||
{
|
||||
memcpy(&((int *)m)[5], a, sizeof(*a));
|
||||
}
|
||||
|
||||
void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
|
||||
{
|
||||
memcpy(a, &((int*)m)[5], sizeof(*a));
|
||||
}
|
||||
|
||||
|
||||
void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str)
|
||||
{
|
||||
u32 usr = msg_user(msg);
|
||||
tipc_printf(buf, str);
|
||||
|
||||
switch (usr) {
|
||||
case MSG_BUNDLER:
|
||||
tipc_printf(buf, "BNDL::");
|
||||
tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg));
|
||||
break;
|
||||
case BCAST_PROTOCOL:
|
||||
tipc_printf(buf, "BCASTP::");
|
||||
break;
|
||||
case MSG_FRAGMENTER:
|
||||
tipc_printf(buf, "FRAGM::");
|
||||
switch (msg_type(msg)) {
|
||||
case FIRST_FRAGMENT:
|
||||
tipc_printf(buf, "FIRST:");
|
||||
break;
|
||||
case FRAGMENT:
|
||||
tipc_printf(buf, "BODY:");
|
||||
break;
|
||||
case LAST_FRAGMENT:
|
||||
tipc_printf(buf, "LAST:");
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
|
||||
|
||||
}
|
||||
tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg),
|
||||
msg_fragm_no(msg));
|
||||
break;
|
||||
case DATA_LOW:
|
||||
case DATA_MEDIUM:
|
||||
case DATA_HIGH:
|
||||
case DATA_CRITICAL:
|
||||
tipc_printf(buf, "DAT%u:", msg_user(msg));
|
||||
if (msg_short(msg)) {
|
||||
tipc_printf(buf, "CON:");
|
||||
break;
|
||||
}
|
||||
switch (msg_type(msg)) {
|
||||
case TIPC_CONN_MSG:
|
||||
tipc_printf(buf, "CON:");
|
||||
break;
|
||||
case TIPC_MCAST_MSG:
|
||||
tipc_printf(buf, "MCST:");
|
||||
break;
|
||||
case TIPC_NAMED_MSG:
|
||||
tipc_printf(buf, "NAM:");
|
||||
break;
|
||||
case TIPC_DIRECT_MSG:
|
||||
tipc_printf(buf, "DIR:");
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg));
|
||||
}
|
||||
if (msg_routed(msg) && !msg_non_seq(msg))
|
||||
tipc_printf(buf, "ROUT:");
|
||||
if (msg_reroute_cnt(msg))
|
||||
tipc_printf(buf, "REROUTED(%u):",
|
||||
msg_reroute_cnt(msg));
|
||||
break;
|
||||
case NAME_DISTRIBUTOR:
|
||||
tipc_printf(buf, "NMD::");
|
||||
switch (msg_type(msg)) {
|
||||
case PUBLICATION:
|
||||
tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */
|
||||
break;
|
||||
case WITHDRAWAL:
|
||||
tipc_printf(buf, "WDRW:");
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
|
||||
}
|
||||
if (msg_routed(msg))
|
||||
tipc_printf(buf, "ROUT:");
|
||||
if (msg_reroute_cnt(msg))
|
||||
tipc_printf(buf, "REROUTED(%u):",
|
||||
msg_reroute_cnt(msg));
|
||||
break;
|
||||
case CONN_MANAGER:
|
||||
tipc_printf(buf, "CONN_MNG:");
|
||||
switch (msg_type(msg)) {
|
||||
case CONN_PROBE:
|
||||
tipc_printf(buf, "PROBE:");
|
||||
break;
|
||||
case CONN_PROBE_REPLY:
|
||||
tipc_printf(buf, "PROBE_REPLY:");
|
||||
break;
|
||||
case CONN_ACK:
|
||||
tipc_printf(buf, "CONN_ACK:");
|
||||
tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg));
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
|
||||
}
|
||||
if (msg_routed(msg))
|
||||
tipc_printf(buf, "ROUT:");
|
||||
if (msg_reroute_cnt(msg))
|
||||
tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg));
|
||||
break;
|
||||
case LINK_PROTOCOL:
|
||||
tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg));
|
||||
switch (msg_type(msg)) {
|
||||
case STATE_MSG:
|
||||
tipc_printf(buf, "STATE:");
|
||||
tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :"");
|
||||
tipc_printf(buf, "NXS(%u):",msg_next_sent(msg));
|
||||
tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg));
|
||||
tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg));
|
||||
break;
|
||||
case RESET_MSG:
|
||||
tipc_printf(buf, "RESET:");
|
||||
if (msg_size(msg) != msg_hdr_sz(msg))
|
||||
tipc_printf(buf, "BEAR:%s:",msg_data(msg));
|
||||
break;
|
||||
case ACTIVATE_MSG:
|
||||
tipc_printf(buf, "ACTIVATE:");
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
|
||||
}
|
||||
tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg));
|
||||
tipc_printf(buf, "SESS(%u):",msg_session(msg));
|
||||
break;
|
||||
case CHANGEOVER_PROTOCOL:
|
||||
tipc_printf(buf, "TUNL:");
|
||||
switch (msg_type(msg)) {
|
||||
case DUPLICATE_MSG:
|
||||
tipc_printf(buf, "DUPL:");
|
||||
break;
|
||||
case ORIGINAL_MSG:
|
||||
tipc_printf(buf, "ORIG:");
|
||||
tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg));
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
|
||||
}
|
||||
break;
|
||||
case ROUTE_DISTRIBUTOR:
|
||||
tipc_printf(buf, "ROUTING_MNG:");
|
||||
switch (msg_type(msg)) {
|
||||
case EXT_ROUTING_TABLE:
|
||||
tipc_printf(buf, "EXT_TBL:");
|
||||
tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
|
||||
break;
|
||||
case LOCAL_ROUTING_TABLE:
|
||||
tipc_printf(buf, "LOCAL_TBL:");
|
||||
tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
|
||||
break;
|
||||
case SLAVE_ROUTING_TABLE:
|
||||
tipc_printf(buf, "DP_TBL:");
|
||||
tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
|
||||
break;
|
||||
case ROUTE_ADDITION:
|
||||
tipc_printf(buf, "ADD:");
|
||||
tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
|
||||
break;
|
||||
case ROUTE_REMOVAL:
|
||||
tipc_printf(buf, "REMOVE:");
|
||||
tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
|
||||
}
|
||||
break;
|
||||
case LINK_CONFIG:
|
||||
tipc_printf(buf, "CFG:");
|
||||
switch (msg_type(msg)) {
|
||||
case DSC_REQ_MSG:
|
||||
tipc_printf(buf, "DSC_REQ:");
|
||||
break;
|
||||
case DSC_RESP_MSG:
|
||||
tipc_printf(buf, "DSC_RESP:");
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN USER:");
|
||||
}
|
||||
|
||||
switch (usr) {
|
||||
case CONN_MANAGER:
|
||||
case NAME_DISTRIBUTOR:
|
||||
case DATA_LOW:
|
||||
case DATA_MEDIUM:
|
||||
case DATA_HIGH:
|
||||
case DATA_CRITICAL:
|
||||
if (msg_short(msg))
|
||||
break; /* No error */
|
||||
switch (msg_errcode(msg)) {
|
||||
case TIPC_OK:
|
||||
break;
|
||||
case TIPC_ERR_NO_NAME:
|
||||
tipc_printf(buf, "NO_NAME:");
|
||||
break;
|
||||
case TIPC_ERR_NO_PORT:
|
||||
tipc_printf(buf, "NO_PORT:");
|
||||
break;
|
||||
case TIPC_ERR_NO_NODE:
|
||||
tipc_printf(buf, "NO_PROC:");
|
||||
break;
|
||||
case TIPC_ERR_OVERLOAD:
|
||||
tipc_printf(buf, "OVERLOAD:");
|
||||
break;
|
||||
case TIPC_CONN_SHUTDOWN:
|
||||
tipc_printf(buf, "SHUTDOWN:");
|
||||
break;
|
||||
default:
|
||||
tipc_printf(buf, "UNKNOWN ERROR(%x):",
|
||||
msg_errcode(msg));
|
||||
}
|
||||
default:{}
|
||||
}
|
||||
|
||||
tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg));
|
||||
tipc_printf(buf, "SZ(%u):", msg_size(msg));
|
||||
tipc_printf(buf, "SQNO(%u):", msg_seqno(msg));
|
||||
|
||||
if (msg_non_seq(msg))
|
||||
tipc_printf(buf, "NOSEQ:");
|
||||
else {
|
||||
tipc_printf(buf, "ACK(%u):", msg_ack(msg));
|
||||
}
|
||||
tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg));
|
||||
tipc_printf(buf, "PRND(%x)", msg_prevnode(msg));
|
||||
|
||||
if (msg_isdata(msg)) {
|
||||
if (msg_named(msg)) {
|
||||
tipc_printf(buf, "NTYP(%u):", msg_nametype(msg));
|
||||
tipc_printf(buf, "NINST(%u)", msg_nameinst(msg));
|
||||
}
|
||||
}
|
||||
|
||||
if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) &&
|
||||
(usr != MSG_BUNDLER)) {
|
||||
if (!msg_short(msg)) {
|
||||
tipc_printf(buf, ":ORIG(%x:%u):",
|
||||
msg_orignode(msg), msg_origport(msg));
|
||||
tipc_printf(buf, ":DEST(%x:%u):",
|
||||
msg_destnode(msg), msg_destport(msg));
|
||||
} else {
|
||||
tipc_printf(buf, ":OPRT(%u):", msg_origport(msg));
|
||||
tipc_printf(buf, ":DPRT(%u):", msg_destport(msg));
|
||||
}
|
||||
if (msg_routed(msg) && !msg_non_seq(msg))
|
||||
tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg));
|
||||
}
|
||||
if (msg_user(msg) == NAME_DISTRIBUTOR) {
|
||||
tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg));
|
||||
tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg));
|
||||
if (msg_routed(msg)) {
|
||||
tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg));
|
||||
}
|
||||
}
|
||||
|
||||
if (msg_user(msg) == LINK_CONFIG) {
|
||||
u32* raw = (u32*)msg;
|
||||
struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5];
|
||||
tipc_printf(buf, ":REQL(%u):", msg_req_links(msg));
|
||||
tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
|
||||
tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
|
||||
media_addr_printf(buf, orig);
|
||||
}
|
||||
if (msg_user(msg) == BCAST_PROTOCOL) {
|
||||
tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg));
|
||||
tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg));
|
||||
}
|
||||
tipc_printf(buf, "\n");
|
||||
if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) {
|
||||
msg_print(buf,msg_get_wrapped(msg)," /");
|
||||
}
|
||||
if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) {
|
||||
msg_print(buf,msg_get_wrapped(msg)," /");
|
||||
}
|
||||
}
|
815
net/tipc/msg.h
Normal file
815
net/tipc/msg.h
Normal file
|
@ -0,0 +1,815 @@
|
|||
/*
|
||||
* net/tipc/msg.h: Include file for TIPC message header routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_MSG_H
|
||||
#define _TIPC_MSG_H
|
||||
|
||||
#include <net/tipc/tipc_msg.h>
|
||||
|
||||
#define TIPC_VERSION 2
|
||||
#define DATA_LOW TIPC_LOW_IMPORTANCE
|
||||
#define DATA_MEDIUM TIPC_MEDIUM_IMPORTANCE
|
||||
#define DATA_HIGH TIPC_HIGH_IMPORTANCE
|
||||
#define DATA_CRITICAL TIPC_CRITICAL_IMPORTANCE
|
||||
#define SHORT_H_SIZE 24 /* Connected,in cluster */
|
||||
#define DIR_MSG_H_SIZE 32 /* Directly addressed messages */
|
||||
#define CONN_MSG_H_SIZE 36 /* Routed connected msgs*/
|
||||
#define LONG_H_SIZE 40 /* Named Messages */
|
||||
#define MCAST_H_SIZE 44 /* Multicast messages */
|
||||
#define MAX_H_SIZE 60 /* Inclusive full options */
|
||||
#define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
|
||||
#define LINK_CONFIG 13
|
||||
|
||||
|
||||
/*
|
||||
TIPC user data message header format, version 2
|
||||
|
||||
- Fundamental definitions available to privileged TIPC users
|
||||
are located in tipc_msg.h.
|
||||
- Remaining definitions available to TIPC internal users appear below.
|
||||
*/
|
||||
|
||||
|
||||
static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val)
|
||||
{
|
||||
m->hdr[w] = htonl(val);
|
||||
}
|
||||
|
||||
static inline void msg_set_bits(struct tipc_msg *m, u32 w,
|
||||
u32 pos, u32 mask, u32 val)
|
||||
{
|
||||
u32 word = msg_word(m,w) & ~(mask << pos);
|
||||
msg_set_word(m, w, (word |= (val << pos)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Word 0
|
||||
*/
|
||||
|
||||
static inline u32 msg_version(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 29, 7);
|
||||
}
|
||||
|
||||
static inline void msg_set_version(struct tipc_msg *m)
|
||||
{
|
||||
msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
|
||||
}
|
||||
|
||||
static inline u32 msg_user(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 25, 0xf);
|
||||
}
|
||||
|
||||
static inline u32 msg_isdata(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_user(m) <= DATA_CRITICAL);
|
||||
}
|
||||
|
||||
static inline void msg_set_user(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 0, 25, 0xf, n);
|
||||
}
|
||||
|
||||
static inline void msg_set_importance(struct tipc_msg *m, u32 i)
|
||||
{
|
||||
msg_set_user(m, i);
|
||||
}
|
||||
|
||||
static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n)
|
||||
{
|
||||
msg_set_bits(m, 0, 21, 0xf, n>>2);
|
||||
}
|
||||
|
||||
static inline int msg_non_seq(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 20, 1);
|
||||
}
|
||||
|
||||
static inline void msg_set_non_seq(struct tipc_msg *m)
|
||||
{
|
||||
msg_set_bits(m, 0, 20, 1, 1);
|
||||
}
|
||||
|
||||
static inline int msg_dest_droppable(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 19, 1);
|
||||
}
|
||||
|
||||
static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d)
|
||||
{
|
||||
msg_set_bits(m, 0, 19, 1, d);
|
||||
}
|
||||
|
||||
static inline int msg_src_droppable(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 0, 18, 1);
|
||||
}
|
||||
|
||||
static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d)
|
||||
{
|
||||
msg_set_bits(m, 0, 18, 1, d);
|
||||
}
|
||||
|
||||
static inline void msg_set_size(struct tipc_msg *m, u32 sz)
|
||||
{
|
||||
m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Word 1
|
||||
*/
|
||||
|
||||
static inline void msg_set_type(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 1, 29, 0x7, n);
|
||||
}
|
||||
|
||||
static inline void msg_set_errcode(struct tipc_msg *m, u32 err)
|
||||
{
|
||||
msg_set_bits(m, 1, 25, 0xf, err);
|
||||
}
|
||||
|
||||
static inline u32 msg_reroute_cnt(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 1, 21, 0xf);
|
||||
}
|
||||
|
||||
static inline void msg_incr_reroute_cnt(struct tipc_msg *m)
|
||||
{
|
||||
msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1);
|
||||
}
|
||||
|
||||
static inline void msg_reset_reroute_cnt(struct tipc_msg *m)
|
||||
{
|
||||
msg_set_bits(m, 1, 21, 0xf, 0);
|
||||
}
|
||||
|
||||
static inline u32 msg_lookup_scope(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 1, 19, 0x3);
|
||||
}
|
||||
|
||||
static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 1, 19, 0x3, n);
|
||||
}
|
||||
|
||||
static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz)
|
||||
{
|
||||
u32 hsz = msg_hdr_sz(m);
|
||||
char *to = (char *)&m->hdr[hsz/4];
|
||||
|
||||
if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE))
|
||||
return;
|
||||
msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4);
|
||||
msg_set_hdr_sz(m, hsz + sz);
|
||||
memcpy(to, opt, sz);
|
||||
}
|
||||
|
||||
static inline u32 msg_bcast_ack(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 1, 0, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 1, 0, 0xffff, n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Word 2
|
||||
*/
|
||||
|
||||
static inline u32 msg_ack(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 2, 16, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_ack(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 2, 16, 0xffff, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_seqno(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 2, 0, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_seqno(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 2, 0, 0xffff, n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Words 3-10
|
||||
*/
|
||||
|
||||
|
||||
static inline void msg_set_prevnode(struct tipc_msg *m, u32 a)
|
||||
{
|
||||
msg_set_word(m, 3, a);
|
||||
}
|
||||
|
||||
static inline void msg_set_origport(struct tipc_msg *m, u32 p)
|
||||
{
|
||||
msg_set_word(m, 4, p);
|
||||
}
|
||||
|
||||
static inline void msg_set_destport(struct tipc_msg *m, u32 p)
|
||||
{
|
||||
msg_set_word(m, 5, p);
|
||||
}
|
||||
|
||||
static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p)
|
||||
{
|
||||
msg_set_word(m, 5, p);
|
||||
}
|
||||
|
||||
static inline void msg_set_orignode(struct tipc_msg *m, u32 a)
|
||||
{
|
||||
msg_set_word(m, 6, a);
|
||||
}
|
||||
|
||||
static inline void msg_set_destnode(struct tipc_msg *m, u32 a)
|
||||
{
|
||||
msg_set_word(m, 7, a);
|
||||
}
|
||||
|
||||
static inline int msg_is_dest(struct tipc_msg *m, u32 d)
|
||||
{
|
||||
return(msg_short(m) || (msg_destnode(m) == d));
|
||||
}
|
||||
|
||||
static inline u32 msg_routed(struct tipc_msg *m)
|
||||
{
|
||||
if (likely(msg_short(m)))
|
||||
return 0;
|
||||
return(msg_destnode(m) ^ msg_orignode(m)) >> 11;
|
||||
}
|
||||
|
||||
static inline void msg_set_nametype(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_word(m, 8, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_transp_seqno(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 8);
|
||||
}
|
||||
|
||||
static inline void msg_set_timestamp(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_word(m, 8, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_timestamp(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 8);
|
||||
}
|
||||
|
||||
static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_word(m, 8, n);
|
||||
}
|
||||
|
||||
static inline void msg_set_namelower(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_word(m, 9, n);
|
||||
}
|
||||
|
||||
static inline void msg_set_nameinst(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_namelower(m, n);
|
||||
}
|
||||
|
||||
static inline void msg_set_nameupper(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_word(m, 10, n);
|
||||
}
|
||||
|
||||
static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
|
||||
{
|
||||
return (struct tipc_msg *)msg_data(m);
|
||||
}
|
||||
|
||||
static inline void msg_expand(struct tipc_msg *m, u32 destnode)
|
||||
{
|
||||
if (!msg_short(m))
|
||||
return;
|
||||
msg_set_hdr_sz(m, LONG_H_SIZE);
|
||||
msg_set_orignode(m, msg_prevnode(m));
|
||||
msg_set_destnode(m, destnode);
|
||||
memset(&m->hdr[8], 0, 12);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
TIPC internal message header format, version 2
|
||||
|
||||
1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w0:|vers |msg usr|hdr sz |n|resrv| packet size |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w1:|m typ|rsv=0| sequence gap | broadcast ack no |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w3:| previous node |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w5:| session no |rsv=0|r|berid|link prio|netpl|p|
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w6:| originating node |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w7:| destination node |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w8:| transport sequence number |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
w9:| msg count / bcast tag | link tolerance |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
\ \
|
||||
/ User Specific Data /
|
||||
\ \
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
NB: CONN_MANAGER use data message format. LINK_CONFIG has own format.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Internal users
|
||||
*/
|
||||
|
||||
#define BCAST_PROTOCOL 5
|
||||
#define MSG_BUNDLER 6
|
||||
#define LINK_PROTOCOL 7
|
||||
#define CONN_MANAGER 8
|
||||
#define ROUTE_DISTRIBUTOR 9
|
||||
#define CHANGEOVER_PROTOCOL 10
|
||||
#define NAME_DISTRIBUTOR 11
|
||||
#define MSG_FRAGMENTER 12
|
||||
#define LINK_CONFIG 13
|
||||
#define INT_H_SIZE 40
|
||||
#define DSC_H_SIZE 40
|
||||
|
||||
/*
|
||||
* Connection management protocol messages
|
||||
*/
|
||||
|
||||
#define CONN_PROBE 0
|
||||
#define CONN_PROBE_REPLY 1
|
||||
#define CONN_ACK 2
|
||||
|
||||
/*
|
||||
* Name distributor messages
|
||||
*/
|
||||
|
||||
#define PUBLICATION 0
|
||||
#define WITHDRAWAL 1
|
||||
|
||||
|
||||
/*
|
||||
* Word 1
|
||||
*/
|
||||
|
||||
static inline u32 msg_seq_gap(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 1, 16, 0xff);
|
||||
}
|
||||
|
||||
static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 1, 16, 0xff, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_req_links(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 1, 16, 0xfff);
|
||||
}
|
||||
|
||||
static inline void msg_set_req_links(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 1, 16, 0xfff, n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Word 2
|
||||
*/
|
||||
|
||||
static inline u32 msg_dest_domain(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 2);
|
||||
}
|
||||
|
||||
static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_word(m, 2, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_bcgap_after(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 2, 16, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 2, 16, 0xffff, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_bcgap_to(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 2, 0, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 2, 0, 0xffff, n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Word 4
|
||||
*/
|
||||
|
||||
static inline u32 msg_last_bcast(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 4, 16, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 4, 16, 0xffff, n);
|
||||
}
|
||||
|
||||
|
||||
static inline u32 msg_fragm_no(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 4, 16, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 4, 16, 0xffff, n);
|
||||
}
|
||||
|
||||
|
||||
static inline u32 msg_next_sent(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 4, 0, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_next_sent(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 4, 0, 0xffff, n);
|
||||
}
|
||||
|
||||
|
||||
static inline u32 msg_long_msgno(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 4, 0, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 4, 0, 0xffff, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_bc_netid(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, 4);
|
||||
}
|
||||
|
||||
static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id)
|
||||
{
|
||||
msg_set_word(m, 4, id);
|
||||
}
|
||||
|
||||
static inline u32 msg_link_selector(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 4, 0, 1);
|
||||
}
|
||||
|
||||
static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 4, 0, 1, (n & 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Word 5
|
||||
*/
|
||||
|
||||
static inline u32 msg_session(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 5, 16, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_session(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 5, 16, 0xffff, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_probe(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 5, 0, 1);
|
||||
}
|
||||
|
||||
static inline void msg_set_probe(struct tipc_msg *m, u32 val)
|
||||
{
|
||||
msg_set_bits(m, 5, 0, 1, (val & 1));
|
||||
}
|
||||
|
||||
static inline char msg_net_plane(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 5, 1, 7) + 'A';
|
||||
}
|
||||
|
||||
static inline void msg_set_net_plane(struct tipc_msg *m, char n)
|
||||
{
|
||||
msg_set_bits(m, 5, 1, 7, (n - 'A'));
|
||||
}
|
||||
|
||||
static inline u32 msg_linkprio(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 5, 4, 0x1f);
|
||||
}
|
||||
|
||||
static inline void msg_set_linkprio(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 5, 4, 0x1f, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_bearer_id(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 5, 9, 0x7);
|
||||
}
|
||||
|
||||
static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 5, 9, 0x7, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_redundant_link(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 5, 12, 0x1);
|
||||
}
|
||||
|
||||
static inline void msg_set_redundant_link(struct tipc_msg *m)
|
||||
{
|
||||
msg_set_bits(m, 5, 12, 0x1, 1);
|
||||
}
|
||||
|
||||
static inline void msg_clear_redundant_link(struct tipc_msg *m)
|
||||
{
|
||||
msg_set_bits(m, 5, 12, 0x1, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Word 9
|
||||
*/
|
||||
|
||||
static inline u32 msg_msgcnt(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 9, 16, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 9, 16, 0xffff, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_bcast_tag(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 9, 16, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 9, 16, 0xffff, n);
|
||||
}
|
||||
|
||||
static inline u32 msg_max_pkt(struct tipc_msg *m)
|
||||
{
|
||||
return (msg_bits(m, 9, 16, 0xffff) * 4);
|
||||
}
|
||||
|
||||
static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 9, 16, 0xffff, (n / 4));
|
||||
}
|
||||
|
||||
static inline u32 msg_link_tolerance(struct tipc_msg *m)
|
||||
{
|
||||
return msg_bits(m, 9, 0, 0xffff);
|
||||
}
|
||||
|
||||
static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
|
||||
{
|
||||
msg_set_bits(m, 9, 0, 0xffff, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routing table message data
|
||||
*/
|
||||
|
||||
|
||||
static inline u32 msg_remote_node(struct tipc_msg *m)
|
||||
{
|
||||
return msg_word(m, msg_hdr_sz(m)/4);
|
||||
}
|
||||
|
||||
static inline void msg_set_remote_node(struct tipc_msg *m, u32 a)
|
||||
{
|
||||
msg_set_word(m, msg_hdr_sz(m)/4, a);
|
||||
}
|
||||
|
||||
static inline int msg_dataoctet(struct tipc_msg *m, u32 pos)
|
||||
{
|
||||
return(msg_data(m)[pos + 4] != 0);
|
||||
}
|
||||
|
||||
static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos)
|
||||
{
|
||||
msg_data(m)[pos + 4] = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Segmentation message types
|
||||
*/
|
||||
|
||||
#define FIRST_FRAGMENT 0
|
||||
#define FRAGMENT 1
|
||||
#define LAST_FRAGMENT 2
|
||||
|
||||
/*
|
||||
* Link management protocol message types
|
||||
*/
|
||||
|
||||
#define STATE_MSG 0
|
||||
#define RESET_MSG 1
|
||||
#define ACTIVATE_MSG 2
|
||||
|
||||
/*
|
||||
* Changeover tunnel message types
|
||||
*/
|
||||
#define DUPLICATE_MSG 0
|
||||
#define ORIGINAL_MSG 1
|
||||
|
||||
/*
|
||||
* Routing table message types
|
||||
*/
|
||||
#define EXT_ROUTING_TABLE 0
|
||||
#define LOCAL_ROUTING_TABLE 1
|
||||
#define SLAVE_ROUTING_TABLE 2
|
||||
#define ROUTE_ADDITION 3
|
||||
#define ROUTE_REMOVAL 4
|
||||
|
||||
/*
|
||||
* Config protocol message types
|
||||
*/
|
||||
|
||||
#define DSC_REQ_MSG 0
|
||||
#define DSC_RESP_MSG 1
|
||||
|
||||
static inline u32 msg_tot_importance(struct tipc_msg *m)
|
||||
{
|
||||
if (likely(msg_isdata(m))) {
|
||||
if (likely(msg_orignode(m) == tipc_own_addr))
|
||||
return msg_importance(m);
|
||||
return msg_importance(m) + 4;
|
||||
}
|
||||
if ((msg_user(m) == MSG_FRAGMENTER) &&
|
||||
(msg_type(m) == FIRST_FRAGMENT))
|
||||
return msg_importance(msg_get_wrapped(m));
|
||||
return msg_importance(m);
|
||||
}
|
||||
|
||||
|
||||
static inline void msg_init(struct tipc_msg *m, u32 user, u32 type,
|
||||
u32 err, u32 hsize, u32 destnode)
|
||||
{
|
||||
memset(m, 0, hsize);
|
||||
msg_set_version(m);
|
||||
msg_set_user(m, user);
|
||||
msg_set_hdr_sz(m, hsize);
|
||||
msg_set_size(m, hsize);
|
||||
msg_set_prevnode(m, tipc_own_addr);
|
||||
msg_set_type(m, type);
|
||||
msg_set_errcode(m, err);
|
||||
if (!msg_short(m)) {
|
||||
msg_set_orignode(m, tipc_own_addr);
|
||||
msg_set_destnode(m, destnode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* msg_calc_data_size - determine total data size for message
|
||||
*/
|
||||
|
||||
static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
|
||||
{
|
||||
int dsz = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_sect; i++)
|
||||
dsz += msg_sect[i].iov_len;
|
||||
return dsz;
|
||||
}
|
||||
|
||||
/**
|
||||
* msg_build - create message using specified header and data
|
||||
*
|
||||
* Note: Caller must not hold any locks in case copy_from_user() is interrupted!
|
||||
*
|
||||
* Returns message data size or errno
|
||||
*/
|
||||
|
||||
static inline int msg_build(struct tipc_msg *hdr,
|
||||
struct iovec const *msg_sect, u32 num_sect,
|
||||
int max_size, int usrmem, struct sk_buff** buf)
|
||||
{
|
||||
int dsz, sz, hsz, pos, res, cnt;
|
||||
|
||||
dsz = msg_calc_data_size(msg_sect, num_sect);
|
||||
if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
|
||||
*buf = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pos = hsz = msg_hdr_sz(hdr);
|
||||
sz = hsz + dsz;
|
||||
msg_set_size(hdr, sz);
|
||||
if (unlikely(sz > max_size)) {
|
||||
*buf = NULL;
|
||||
return dsz;
|
||||
}
|
||||
|
||||
*buf = buf_acquire(sz);
|
||||
if (!(*buf))
|
||||
return -ENOMEM;
|
||||
memcpy((*buf)->data, (unchar *)hdr, hsz);
|
||||
for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
|
||||
if (likely(usrmem))
|
||||
res = !copy_from_user((*buf)->data + pos,
|
||||
msg_sect[cnt].iov_base,
|
||||
msg_sect[cnt].iov_len);
|
||||
else
|
||||
memcpy((*buf)->data + pos, msg_sect[cnt].iov_base,
|
||||
msg_sect[cnt].iov_len);
|
||||
pos += msg_sect[cnt].iov_len;
|
||||
}
|
||||
if (likely(res))
|
||||
return dsz;
|
||||
|
||||
buf_discard(*buf);
|
||||
*buf = NULL;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
struct tipc_media_addr;
|
||||
|
||||
extern void msg_set_media_addr(struct tipc_msg *m,
|
||||
struct tipc_media_addr *a);
|
||||
|
||||
extern void msg_get_media_addr(struct tipc_msg *m,
|
||||
struct tipc_media_addr *a);
|
||||
|
||||
|
||||
#endif
|
306
net/tipc/name_distr.c
Normal file
306
net/tipc/name_distr.c
Normal file
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* net/tipc/name_distr.c: TIPC name distribution code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "cluster.h"
|
||||
#include "dbg.h"
|
||||
#include "link.h"
|
||||
#include "msg.h"
|
||||
#include "name_distr.h"
|
||||
|
||||
#undef DBG_OUTPUT
|
||||
#define DBG_OUTPUT NULL
|
||||
|
||||
#define ITEM_SIZE sizeof(struct distr_item)
|
||||
|
||||
/**
|
||||
* struct distr_item - publication info distributed to other nodes
|
||||
* @type: name sequence type
|
||||
* @lower: name sequence lower bound
|
||||
* @upper: name sequence upper bound
|
||||
* @ref: publishing port reference
|
||||
* @key: publication key
|
||||
*
|
||||
* ===> All fields are stored in network byte order. <===
|
||||
*
|
||||
* First 3 fields identify (name or) name sequence being published.
|
||||
* Reference field uniquely identifies port that published name sequence.
|
||||
* Key field uniquely identifies publication, in the event a port has
|
||||
* multiple publications of the same name sequence.
|
||||
*
|
||||
* Note: There is no field that identifies the publishing node because it is
|
||||
* the same for all items contained within a publication message.
|
||||
*/
|
||||
|
||||
struct distr_item {
|
||||
u32 type;
|
||||
u32 lower;
|
||||
u32 upper;
|
||||
u32 ref;
|
||||
u32 key;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of externally visible publications by this node --
|
||||
* that is, all publications having scope > TIPC_NODE_SCOPE.
|
||||
*/
|
||||
|
||||
static LIST_HEAD(publ_root);
|
||||
static u32 publ_cnt = 0;
|
||||
|
||||
/**
|
||||
* publ_to_item - add publication info to a publication message
|
||||
*/
|
||||
|
||||
static void publ_to_item(struct distr_item *i, struct publication *p)
|
||||
{
|
||||
i->type = htonl(p->type);
|
||||
i->lower = htonl(p->lower);
|
||||
i->upper = htonl(p->upper);
|
||||
i->ref = htonl(p->ref);
|
||||
i->key = htonl(p->key);
|
||||
dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper);
|
||||
}
|
||||
|
||||
/**
|
||||
* named_prepare_buf - allocate & initialize a publication message
|
||||
*/
|
||||
|
||||
static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
|
||||
{
|
||||
struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size);
|
||||
struct tipc_msg *msg;
|
||||
|
||||
if (buf != NULL) {
|
||||
msg = buf_msg(buf);
|
||||
msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK,
|
||||
LONG_H_SIZE, dest);
|
||||
msg_set_size(msg, LONG_H_SIZE + size);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* named_publish - tell other nodes about a new publication by this node
|
||||
*/
|
||||
|
||||
void named_publish(struct publication *publ)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct distr_item *item;
|
||||
|
||||
list_add(&publ->local_list, &publ_root);
|
||||
publ_cnt++;
|
||||
|
||||
buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
|
||||
if (!buf) {
|
||||
warn("Memory squeeze; failed to distribute publication\n");
|
||||
return;
|
||||
}
|
||||
|
||||
item = (struct distr_item *)msg_data(buf_msg(buf));
|
||||
publ_to_item(item, publ);
|
||||
dbg("named_withdraw: broadcasting publish msg\n");
|
||||
cluster_broadcast(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* named_withdraw - tell other nodes about a withdrawn publication by this node
|
||||
*/
|
||||
|
||||
void named_withdraw(struct publication *publ)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct distr_item *item;
|
||||
|
||||
list_del(&publ->local_list);
|
||||
publ_cnt--;
|
||||
|
||||
buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0);
|
||||
if (!buf) {
|
||||
warn("Memory squeeze; failed to distribute withdrawal\n");
|
||||
return;
|
||||
}
|
||||
|
||||
item = (struct distr_item *)msg_data(buf_msg(buf));
|
||||
publ_to_item(item, publ);
|
||||
dbg("named_withdraw: broadcasting withdraw msg\n");
|
||||
cluster_broadcast(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* named_node_up - tell specified node about all publications by this node
|
||||
*/
|
||||
|
||||
void named_node_up(unsigned long node)
|
||||
{
|
||||
struct publication *publ;
|
||||
struct distr_item *item = 0;
|
||||
struct sk_buff *buf = 0;
|
||||
u32 left = 0;
|
||||
u32 rest;
|
||||
u32 max_item_buf;
|
||||
|
||||
assert(in_own_cluster(node));
|
||||
read_lock_bh(&nametbl_lock);
|
||||
max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
|
||||
max_item_buf *= ITEM_SIZE;
|
||||
rest = publ_cnt * ITEM_SIZE;
|
||||
|
||||
list_for_each_entry(publ, &publ_root, local_list) {
|
||||
if (!buf) {
|
||||
left = (rest <= max_item_buf) ? rest : max_item_buf;
|
||||
rest -= left;
|
||||
buf = named_prepare_buf(PUBLICATION, left, node);
|
||||
if (buf == NULL) {
|
||||
warn("Memory Squeeze; could not send publication\n");
|
||||
goto exit;
|
||||
}
|
||||
item = (struct distr_item *)msg_data(buf_msg(buf));
|
||||
}
|
||||
publ_to_item(item, publ);
|
||||
item++;
|
||||
left -= ITEM_SIZE;
|
||||
if (!left) {
|
||||
msg_set_link_selector(buf_msg(buf), node);
|
||||
dbg("named_node_up: sending publish msg to "
|
||||
"<%u.%u.%u>\n", tipc_zone(node),
|
||||
tipc_cluster(node), tipc_node(node));
|
||||
link_send(buf, node, node);
|
||||
buf = 0;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
read_unlock_bh(&nametbl_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* node_is_down - remove publication associated with a failed node
|
||||
*
|
||||
* Invoked for each publication issued by a newly failed node.
|
||||
* Removes publication structure from name table & deletes it.
|
||||
* In rare cases the link may have come back up again when this
|
||||
* function is called, and we have two items representing the same
|
||||
* publication. Nudge this item's key to distinguish it from the other.
|
||||
* (Note: Publication's node subscription is already unsubscribed.)
|
||||
*/
|
||||
|
||||
static void node_is_down(struct publication *publ)
|
||||
{
|
||||
struct publication *p;
|
||||
write_lock_bh(&nametbl_lock);
|
||||
dbg("node_is_down: withdrawing %u, %u, %u\n",
|
||||
publ->type, publ->lower, publ->upper);
|
||||
publ->key += 1222345;
|
||||
p = nametbl_remove_publ(publ->type, publ->lower,
|
||||
publ->node, publ->ref, publ->key);
|
||||
assert(p == publ);
|
||||
write_unlock_bh(&nametbl_lock);
|
||||
if (publ)
|
||||
kfree(publ);
|
||||
}
|
||||
|
||||
/**
|
||||
* named_recv - process name table update message sent by another node
|
||||
*/
|
||||
|
||||
void named_recv(struct sk_buff *buf)
|
||||
{
|
||||
struct publication *publ;
|
||||
struct tipc_msg *msg = buf_msg(buf);
|
||||
struct distr_item *item = (struct distr_item *)msg_data(msg);
|
||||
u32 count = msg_data_sz(msg) / ITEM_SIZE;
|
||||
|
||||
write_lock_bh(&nametbl_lock);
|
||||
while (count--) {
|
||||
if (msg_type(msg) == PUBLICATION) {
|
||||
dbg("named_recv: got publication for %u, %u, %u\n",
|
||||
ntohl(item->type), ntohl(item->lower),
|
||||
ntohl(item->upper));
|
||||
publ = nametbl_insert_publ(ntohl(item->type),
|
||||
ntohl(item->lower),
|
||||
ntohl(item->upper),
|
||||
TIPC_CLUSTER_SCOPE,
|
||||
msg_orignode(msg),
|
||||
ntohl(item->ref),
|
||||
ntohl(item->key));
|
||||
if (publ) {
|
||||
nodesub_subscribe(&publ->subscr,
|
||||
msg_orignode(msg),
|
||||
publ,
|
||||
(net_ev_handler)node_is_down);
|
||||
}
|
||||
} else if (msg_type(msg) == WITHDRAWAL) {
|
||||
dbg("named_recv: got withdrawl for %u, %u, %u\n",
|
||||
ntohl(item->type), ntohl(item->lower),
|
||||
ntohl(item->upper));
|
||||
publ = nametbl_remove_publ(ntohl(item->type),
|
||||
ntohl(item->lower),
|
||||
msg_orignode(msg),
|
||||
ntohl(item->ref),
|
||||
ntohl(item->key));
|
||||
|
||||
if (publ) {
|
||||
nodesub_unsubscribe(&publ->subscr);
|
||||
kfree(publ);
|
||||
}
|
||||
} else {
|
||||
warn("named_recv: unknown msg\n");
|
||||
}
|
||||
item++;
|
||||
}
|
||||
write_unlock_bh(&nametbl_lock);
|
||||
buf_discard(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* named_reinit - re-initialize local publication list
|
||||
*
|
||||
* This routine is called whenever TIPC networking is (re)enabled.
|
||||
* All existing publications by this node that have "cluster" or "zone" scope
|
||||
* are updated to reflect the node's current network address.
|
||||
* (If the node's address is unchanged, the update loop terminates immediately.)
|
||||
*/
|
||||
|
||||
void named_reinit(void)
|
||||
{
|
||||
struct publication *publ;
|
||||
|
||||
write_lock_bh(&nametbl_lock);
|
||||
list_for_each_entry(publ, &publ_root, local_list) {
|
||||
if (publ->node == tipc_own_addr)
|
||||
break;
|
||||
publ->node = tipc_own_addr;
|
||||
}
|
||||
write_unlock_bh(&nametbl_lock);
|
||||
}
|
45
net/tipc/name_distr.h
Normal file
45
net/tipc/name_distr.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* net/tipc/name_distr.h: Include file for TIPC name distribution code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_NAME_DISTR_H
|
||||
#define _TIPC_NAME_DISTR_H
|
||||
|
||||
#include "name_table.h"
|
||||
|
||||
void named_publish(struct publication *publ);
|
||||
void named_withdraw(struct publication *publ);
|
||||
void named_node_up(unsigned long node);
|
||||
void named_recv(struct sk_buff *buf);
|
||||
void named_reinit(void);
|
||||
|
||||
#endif
|
1076
net/tipc/name_table.c
Normal file
1076
net/tipc/name_table.c
Normal file
File diff suppressed because it is too large
Load diff
105
net/tipc/name_table.h
Normal file
105
net/tipc/name_table.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* net/tipc/name_table.h: Include file for TIPC name table code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_NAME_TABLE_H
|
||||
#define _TIPC_NAME_TABLE_H
|
||||
|
||||
#include "node_subscr.h"
|
||||
|
||||
struct subscription;
|
||||
struct port_list;
|
||||
|
||||
/*
|
||||
* TIPC name types reserved for internal TIPC use (both current and planned)
|
||||
*/
|
||||
|
||||
#define TIPC_ZM_SRV 3 /* zone master service name type */
|
||||
|
||||
|
||||
/**
|
||||
* struct publication - info about a published (name or) name sequence
|
||||
* @type: name sequence type
|
||||
* @lower: name sequence lower bound
|
||||
* @upper: name sequence upper bound
|
||||
* @scope: scope of publication
|
||||
* @node: network address of publishing port's node
|
||||
* @ref: publishing port
|
||||
* @key: publication key
|
||||
* @subscr: subscription to "node down" event (for off-node publications only)
|
||||
* @local_list: adjacent entries in list of publications made by this node
|
||||
* @pport_list: adjacent entries in list of publications made by this port
|
||||
* @node_list: next matching name seq publication with >= node scope
|
||||
* @cluster_list: next matching name seq publication with >= cluster scope
|
||||
* @zone_list: next matching name seq publication with >= zone scope
|
||||
*
|
||||
* Note that the node list, cluster list, and zone list are circular lists.
|
||||
*/
|
||||
|
||||
struct publication {
|
||||
u32 type;
|
||||
u32 lower;
|
||||
u32 upper;
|
||||
u32 scope;
|
||||
u32 node;
|
||||
u32 ref;
|
||||
u32 key;
|
||||
struct node_subscr subscr;
|
||||
struct list_head local_list;
|
||||
struct list_head pport_list;
|
||||
struct publication *node_list_next;
|
||||
struct publication *cluster_list_next;
|
||||
struct publication *zone_list_next;
|
||||
};
|
||||
|
||||
|
||||
extern rwlock_t nametbl_lock;
|
||||
|
||||
struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space);
|
||||
u32 nametbl_translate(u32 type, u32 instance, u32 *node);
|
||||
int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
|
||||
struct port_list *dports);
|
||||
int nametbl_publish_rsv(u32 ref, unsigned int scope,
|
||||
struct tipc_name_seq const *seq);
|
||||
struct publication *nametbl_publish(u32 type, u32 lower, u32 upper,
|
||||
u32 scope, u32 port_ref, u32 key);
|
||||
int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
|
||||
struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper,
|
||||
u32 scope, u32 node, u32 ref, u32 key);
|
||||
struct publication *nametbl_remove_publ(u32 type, u32 lower,
|
||||
u32 node, u32 ref, u32 key);
|
||||
void nametbl_subscribe(struct subscription *s);
|
||||
void nametbl_unsubscribe(struct subscription *s);
|
||||
int nametbl_init(void);
|
||||
void nametbl_stop(void);
|
||||
|
||||
#endif
|
308
net/tipc/net.c
Normal file
308
net/tipc/net.c
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* net/tipc/net.c: TIPC network routing code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "bearer.h"
|
||||
#include "net.h"
|
||||
#include "zone.h"
|
||||
#include "addr.h"
|
||||
#include "name_table.h"
|
||||
#include "name_distr.h"
|
||||
#include "subscr.h"
|
||||
#include "link.h"
|
||||
#include "msg.h"
|
||||
#include "port.h"
|
||||
#include "bcast.h"
|
||||
#include "discover.h"
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* The TIPC locking policy is designed to ensure a very fine locking
|
||||
* granularity, permitting complete parallel access to individual
|
||||
* port and node/link instances. The code consists of three major
|
||||
* locking domains, each protected with their own disjunct set of locks.
|
||||
*
|
||||
* 1: The routing hierarchy.
|
||||
* Comprises the structures 'zone', 'cluster', 'node', 'link'
|
||||
* and 'bearer'. The whole hierarchy is protected by a big
|
||||
* read/write lock, net_lock, to enssure that nothing is added
|
||||
* or removed while code is accessing any of these structures.
|
||||
* This layer must not be called from the two others while they
|
||||
* hold any of their own locks.
|
||||
* Neither must it itself do any upcalls to the other two before
|
||||
* it has released net_lock and other protective locks.
|
||||
*
|
||||
* Within the net_lock domain there are two sub-domains;'node' and
|
||||
* 'bearer', where local write operations are permitted,
|
||||
* provided that those are protected by individual spin_locks
|
||||
* per instance. Code holding net_lock(read) and a node spin_lock
|
||||
* is permitted to poke around in both the node itself and its
|
||||
* subordinate links. I.e, it can update link counters and queues,
|
||||
* change link state, send protocol messages, and alter the
|
||||
* "active_links" array in the node; but it can _not_ remove a link
|
||||
* or a node from the overall structure.
|
||||
* Correspondingly, individual bearers may change status within a
|
||||
* net_lock(read), protected by an individual spin_lock ber bearer
|
||||
* instance, but it needs net_lock(write) to remove/add any bearers.
|
||||
*
|
||||
*
|
||||
* 2: The transport level of the protocol.
|
||||
* This consists of the structures port, (and its user level
|
||||
* representations, such as user_port and tipc_sock), reference and
|
||||
* tipc_user (port.c, reg.c, socket.c).
|
||||
*
|
||||
* This layer has four different locks:
|
||||
* - The tipc_port spin_lock. This is protecting each port instance
|
||||
* from parallel data access and removal. Since we can not place
|
||||
* this lock in the port itself, it has been placed in the
|
||||
* corresponding reference table entry, which has the same life
|
||||
* cycle as the module. This entry is difficult to access from
|
||||
* outside the TIPC core, however, so a pointer to the lock has
|
||||
* been added in the port instance, -to be used for unlocking
|
||||
* only.
|
||||
* - A read/write lock to protect the reference table itself (teg.c).
|
||||
* (Nobody is using read-only access to this, so it can just as
|
||||
* well be changed to a spin_lock)
|
||||
* - A spin lock to protect the registry of kernel/driver users (reg.c)
|
||||
* - A global spin_lock (port_lock), which only task is to ensure
|
||||
* consistency where more than one port is involved in an operation,
|
||||
* i.e., whe a port is part of a linked list of ports.
|
||||
* There are two such lists; 'port_list', which is used for management,
|
||||
* and 'wait_list', which is used to queue ports during congestion.
|
||||
*
|
||||
* 3: The name table (name_table.c, name_distr.c, subscription.c)
|
||||
* - There is one big read/write-lock (nametbl_lock) protecting the
|
||||
* overall name table structure. Nothing must be added/removed to
|
||||
* this structure without holding write access to it.
|
||||
* - There is one local spin_lock per sub_sequence, which can be seen
|
||||
* as a sub-domain to the nametbl_lock domain. It is used only
|
||||
* for translation operations, and is needed because a translation
|
||||
* steps the root of the 'publication' linked list between each lookup.
|
||||
* This is always used within the scope of a nametbl_lock(read).
|
||||
* - A local spin_lock protecting the queue of subscriber events.
|
||||
*/
|
||||
|
||||
rwlock_t net_lock = RW_LOCK_UNLOCKED;
|
||||
struct network net = { 0 };
|
||||
|
||||
struct node *net_select_remote_node(u32 addr, u32 ref)
|
||||
{
|
||||
return zone_select_remote_node(net.zones[tipc_zone(addr)], addr, ref);
|
||||
}
|
||||
|
||||
u32 net_select_router(u32 addr, u32 ref)
|
||||
{
|
||||
return zone_select_router(net.zones[tipc_zone(addr)], addr, ref);
|
||||
}
|
||||
|
||||
|
||||
u32 net_next_node(u32 a)
|
||||
{
|
||||
if (net.zones[tipc_zone(a)])
|
||||
return zone_next_node(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void net_remove_as_router(u32 router)
|
||||
{
|
||||
u32 z_num;
|
||||
|
||||
for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
|
||||
if (!net.zones[z_num])
|
||||
continue;
|
||||
zone_remove_as_router(net.zones[z_num], router);
|
||||
}
|
||||
}
|
||||
|
||||
void net_send_external_routes(u32 dest)
|
||||
{
|
||||
u32 z_num;
|
||||
|
||||
for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
|
||||
if (net.zones[z_num])
|
||||
zone_send_external_routes(net.zones[z_num], dest);
|
||||
}
|
||||
}
|
||||
|
||||
int net_init(void)
|
||||
{
|
||||
u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1);
|
||||
|
||||
memset(&net, 0, sizeof(net));
|
||||
net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC);
|
||||
if (!net.zones) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(net.zones, 0, sz);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
void net_stop(void)
|
||||
{
|
||||
u32 z_num;
|
||||
|
||||
if (!net.zones)
|
||||
return;
|
||||
|
||||
for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
|
||||
zone_delete(net.zones[z_num]);
|
||||
}
|
||||
kfree(net.zones);
|
||||
net.zones = 0;
|
||||
}
|
||||
|
||||
static void net_route_named_msg(struct sk_buff *buf)
|
||||
{
|
||||
struct tipc_msg *msg = buf_msg(buf);
|
||||
u32 dnode;
|
||||
u32 dport;
|
||||
|
||||
if (!msg_named(msg)) {
|
||||
msg_dbg(msg, "net->drop_nam:");
|
||||
buf_discard(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
dnode = addr_domain(msg_lookup_scope(msg));
|
||||
dport = nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode);
|
||||
dbg("net->lookup<%u,%u>-><%u,%x>\n",
|
||||
msg_nametype(msg), msg_nameinst(msg), dport, dnode);
|
||||
if (dport) {
|
||||
msg_set_destnode(msg, dnode);
|
||||
msg_set_destport(msg, dport);
|
||||
net_route_msg(buf);
|
||||
return;
|
||||
}
|
||||
msg_dbg(msg, "net->rej:NO NAME: ");
|
||||
tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
|
||||
}
|
||||
|
||||
void net_route_msg(struct sk_buff *buf)
|
||||
{
|
||||
struct tipc_msg *msg;
|
||||
u32 dnode;
|
||||
|
||||
if (!buf)
|
||||
return;
|
||||
msg = buf_msg(buf);
|
||||
|
||||
msg_incr_reroute_cnt(msg);
|
||||
if (msg_reroute_cnt(msg) > 6) {
|
||||
if (msg_errcode(msg)) {
|
||||
msg_dbg(msg, "NET>DISC>:");
|
||||
buf_discard(buf);
|
||||
} else {
|
||||
msg_dbg(msg, "NET>REJ>:");
|
||||
tipc_reject_msg(buf, msg_destport(msg) ?
|
||||
TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
msg_dbg(msg, "net->rout: ");
|
||||
|
||||
/* Handle message for this node */
|
||||
dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg);
|
||||
if (in_scope(dnode, tipc_own_addr)) {
|
||||
if (msg_isdata(msg)) {
|
||||
if (msg_mcast(msg))
|
||||
port_recv_mcast(buf, NULL);
|
||||
else if (msg_destport(msg))
|
||||
port_recv_msg(buf);
|
||||
else
|
||||
net_route_named_msg(buf);
|
||||
return;
|
||||
}
|
||||
switch (msg_user(msg)) {
|
||||
case ROUTE_DISTRIBUTOR:
|
||||
cluster_recv_routing_table(buf);
|
||||
break;
|
||||
case NAME_DISTRIBUTOR:
|
||||
named_recv(buf);
|
||||
break;
|
||||
case CONN_MANAGER:
|
||||
port_recv_proto_msg(buf);
|
||||
break;
|
||||
default:
|
||||
msg_dbg(msg,"DROP/NET/<REC<");
|
||||
buf_discard(buf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle message for another node */
|
||||
msg_dbg(msg, "NET>SEND>: ");
|
||||
link_send(buf, dnode, msg_link_selector(msg));
|
||||
}
|
||||
|
||||
int tipc_start_net(void)
|
||||
{
|
||||
char addr_string[16];
|
||||
int res;
|
||||
|
||||
if (tipc_mode != TIPC_NODE_MODE)
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
tipc_mode = TIPC_NET_MODE;
|
||||
named_reinit();
|
||||
port_reinit();
|
||||
|
||||
if ((res = bearer_init()) ||
|
||||
(res = net_init()) ||
|
||||
(res = cluster_init()) ||
|
||||
(res = bclink_init())) {
|
||||
return res;
|
||||
}
|
||||
subscr_stop();
|
||||
cfg_stop();
|
||||
k_signal((Handler)subscr_start, 0);
|
||||
k_signal((Handler)cfg_init, 0);
|
||||
info("Started in network mode\n");
|
||||
info("Own node address %s, network identity %u\n",
|
||||
addr_string_fill(addr_string, tipc_own_addr), tipc_net_id);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
void tipc_stop_net(void)
|
||||
{
|
||||
if (tipc_mode != TIPC_NET_MODE)
|
||||
return;
|
||||
write_lock_bh(&net_lock);
|
||||
bearer_stop();
|
||||
tipc_mode = TIPC_NODE_MODE;
|
||||
bclink_stop();
|
||||
net_stop();
|
||||
write_unlock_bh(&net_lock);
|
||||
info("Left network mode \n");
|
||||
}
|
||||
|
63
net/tipc/net.h
Normal file
63
net/tipc/net.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* net/tipc/net.h: Include file for TIPC network routing code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_NET_H
|
||||
#define _TIPC_NET_H
|
||||
|
||||
struct _zone;
|
||||
|
||||
/**
|
||||
* struct network - TIPC network structure
|
||||
* @zones: array of pointers to all zones within network
|
||||
*/
|
||||
|
||||
struct network {
|
||||
struct _zone **zones;
|
||||
};
|
||||
|
||||
|
||||
extern struct network net;
|
||||
extern rwlock_t net_lock;
|
||||
|
||||
int net_init(void);
|
||||
void net_stop(void);
|
||||
void net_remove_as_router(u32 router);
|
||||
void net_send_external_routes(u32 dest);
|
||||
void net_route_msg(struct sk_buff *buf);
|
||||
struct node *net_select_remote_node(u32 addr, u32 ref);
|
||||
u32 net_select_router(u32 addr, u32 ref);
|
||||
|
||||
int tipc_start_net(void);
|
||||
void tipc_stop_net(void);
|
||||
|
||||
#endif
|
107
net/tipc/netlink.c
Normal file
107
net/tipc/netlink.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* net/tipc/netlink.c: TIPC configuration handling
|
||||
*
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "config.h"
|
||||
#include <net/genetlink.h>
|
||||
|
||||
static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct sk_buff *rep_buf;
|
||||
struct nlmsghdr *rep_nlh;
|
||||
struct nlmsghdr *req_nlh = info->nlhdr;
|
||||
struct tipc_genlmsghdr *req_userhdr = info->userhdr;
|
||||
int hdr_space = NLMSG_SPACE(0);
|
||||
|
||||
if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
|
||||
rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
|
||||
else
|
||||
rep_buf = cfg_do_cmd(req_userhdr->dest,
|
||||
req_userhdr->cmd,
|
||||
NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
|
||||
NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
|
||||
hdr_space);
|
||||
|
||||
if (rep_buf) {
|
||||
skb_push(rep_buf, hdr_space);
|
||||
rep_nlh = (struct nlmsghdr *)rep_buf->data;
|
||||
memcpy(rep_nlh, req_nlh, hdr_space);
|
||||
rep_nlh->nlmsg_len = rep_buf->len;
|
||||
genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct genl_family family = {
|
||||
.id = TIPC_GENL_FAMILY,
|
||||
.name = TIPC_GENL_NAME,
|
||||
.version = TIPC_GENL_VERSION,
|
||||
.hdrsize = TIPC_GENL_HDRLEN,
|
||||
.maxattr = 0,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct genl_ops ops = {
|
||||
.cmd = TIPC_GENL_CMD,
|
||||
.doit = handle_cmd,
|
||||
};
|
||||
|
||||
static int family_registered = 0;
|
||||
|
||||
int netlink_start(void)
|
||||
{
|
||||
if (genl_register_family(&family))
|
||||
goto err;
|
||||
|
||||
family_registered = 1;
|
||||
|
||||
if (genl_register_ops(&family, &ops))
|
||||
goto err_unregister;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister:
|
||||
genl_unregister_family(&family);
|
||||
family_registered = 0;
|
||||
err:
|
||||
err("Failed to register netlink interface");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
void netlink_stop(void)
|
||||
{
|
||||
if (family_registered) {
|
||||
genl_unregister_family(&family);
|
||||
family_registered = 0;
|
||||
}
|
||||
}
|
676
net/tipc/node.c
Normal file
676
net/tipc/node.c
Normal file
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
* net/tipc/node.c: TIPC node management routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "config.h"
|
||||
#include "node.h"
|
||||
#include "cluster.h"
|
||||
#include "net.h"
|
||||
#include "addr.h"
|
||||
#include "node_subscr.h"
|
||||
#include "link.h"
|
||||
#include "port.h"
|
||||
#include "bearer.h"
|
||||
#include "name_distr.h"
|
||||
#include "net.h"
|
||||
|
||||
void node_print(struct print_buf *buf, struct node *n_ptr, char *str);
|
||||
static void node_lost_contact(struct node *n_ptr);
|
||||
static void node_established_contact(struct node *n_ptr);
|
||||
|
||||
struct node *nodes = NULL; /* sorted list of nodes within cluster */
|
||||
|
||||
u32 tipc_own_tag = 0;
|
||||
|
||||
struct node *node_create(u32 addr)
|
||||
{
|
||||
struct cluster *c_ptr;
|
||||
struct node *n_ptr;
|
||||
struct node **curr_node;
|
||||
|
||||
n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC);
|
||||
if (n_ptr != NULL) {
|
||||
memset(n_ptr, 0, sizeof(*n_ptr));
|
||||
n_ptr->addr = addr;
|
||||
n_ptr->lock = SPIN_LOCK_UNLOCKED;
|
||||
INIT_LIST_HEAD(&n_ptr->nsub);
|
||||
|
||||
c_ptr = cluster_find(addr);
|
||||
if (c_ptr == NULL)
|
||||
c_ptr = cluster_create(addr);
|
||||
if (c_ptr != NULL) {
|
||||
n_ptr->owner = c_ptr;
|
||||
cluster_attach_node(c_ptr, n_ptr);
|
||||
n_ptr->last_router = -1;
|
||||
|
||||
/* Insert node into ordered list */
|
||||
for (curr_node = &nodes; *curr_node;
|
||||
curr_node = &(*curr_node)->next) {
|
||||
if (addr < (*curr_node)->addr) {
|
||||
n_ptr->next = *curr_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*curr_node) = n_ptr;
|
||||
} else {
|
||||
kfree(n_ptr);
|
||||
n_ptr = NULL;
|
||||
}
|
||||
}
|
||||
return n_ptr;
|
||||
}
|
||||
|
||||
void node_delete(struct node *n_ptr)
|
||||
{
|
||||
if (!n_ptr)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
/* Not needed because links are already deleted via bearer_stop() */
|
||||
|
||||
u32 l_num;
|
||||
|
||||
for (l_num = 0; l_num < MAX_BEARERS; l_num++) {
|
||||
link_delete(n_ptr->links[l_num]);
|
||||
}
|
||||
#endif
|
||||
|
||||
dbg("node %x deleted\n", n_ptr->addr);
|
||||
kfree(n_ptr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* node_link_up - handle addition of link
|
||||
*
|
||||
* Link becomes active (alone or shared) or standby, depending on its priority.
|
||||
*/
|
||||
|
||||
void node_link_up(struct node *n_ptr, struct link *l_ptr)
|
||||
{
|
||||
struct link **active = &n_ptr->active_links[0];
|
||||
|
||||
info("Established link <%s> on network plane %c\n",
|
||||
l_ptr->name, l_ptr->b_ptr->net_plane);
|
||||
|
||||
if (!active[0]) {
|
||||
dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]);
|
||||
active[0] = active[1] = l_ptr;
|
||||
node_established_contact(n_ptr);
|
||||
return;
|
||||
}
|
||||
if (l_ptr->priority < active[0]->priority) {
|
||||
info("Link is standby\n");
|
||||
return;
|
||||
}
|
||||
link_send_duplicate(active[0], l_ptr);
|
||||
if (l_ptr->priority == active[0]->priority) {
|
||||
active[0] = l_ptr;
|
||||
return;
|
||||
}
|
||||
info("Link <%s> on network plane %c becomes standby\n",
|
||||
active[0]->name, active[0]->b_ptr->net_plane);
|
||||
active[0] = active[1] = l_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* node_select_active_links - select active link
|
||||
*/
|
||||
|
||||
static void node_select_active_links(struct node *n_ptr)
|
||||
{
|
||||
struct link **active = &n_ptr->active_links[0];
|
||||
u32 i;
|
||||
u32 highest_prio = 0;
|
||||
|
||||
active[0] = active[1] = 0;
|
||||
|
||||
for (i = 0; i < MAX_BEARERS; i++) {
|
||||
struct link *l_ptr = n_ptr->links[i];
|
||||
|
||||
if (!l_ptr || !link_is_up(l_ptr) ||
|
||||
(l_ptr->priority < highest_prio))
|
||||
continue;
|
||||
|
||||
if (l_ptr->priority > highest_prio) {
|
||||
highest_prio = l_ptr->priority;
|
||||
active[0] = active[1] = l_ptr;
|
||||
} else {
|
||||
active[1] = l_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* node_link_down - handle loss of link
|
||||
*/
|
||||
|
||||
void node_link_down(struct node *n_ptr, struct link *l_ptr)
|
||||
{
|
||||
struct link **active;
|
||||
|
||||
if (!link_is_active(l_ptr)) {
|
||||
info("Lost standby link <%s> on network plane %c\n",
|
||||
l_ptr->name, l_ptr->b_ptr->net_plane);
|
||||
return;
|
||||
}
|
||||
info("Lost link <%s> on network plane %c\n",
|
||||
l_ptr->name, l_ptr->b_ptr->net_plane);
|
||||
|
||||
active = &n_ptr->active_links[0];
|
||||
if (active[0] == l_ptr)
|
||||
active[0] = active[1];
|
||||
if (active[1] == l_ptr)
|
||||
active[1] = active[0];
|
||||
if (active[0] == l_ptr)
|
||||
node_select_active_links(n_ptr);
|
||||
if (node_is_up(n_ptr))
|
||||
link_changeover(l_ptr);
|
||||
else
|
||||
node_lost_contact(n_ptr);
|
||||
}
|
||||
|
||||
int node_has_active_links(struct node *n_ptr)
|
||||
{
|
||||
return (n_ptr &&
|
||||
((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
|
||||
}
|
||||
|
||||
int node_has_redundant_links(struct node *n_ptr)
|
||||
{
|
||||
return (node_has_active_links(n_ptr) &&
|
||||
(n_ptr->active_links[0] != n_ptr->active_links[1]));
|
||||
}
|
||||
|
||||
int node_has_active_routes(struct node *n_ptr)
|
||||
{
|
||||
return (n_ptr && (n_ptr->last_router >= 0));
|
||||
}
|
||||
|
||||
int node_is_up(struct node *n_ptr)
|
||||
{
|
||||
return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr));
|
||||
}
|
||||
|
||||
struct node *node_attach_link(struct link *l_ptr)
|
||||
{
|
||||
struct node *n_ptr = node_find(l_ptr->addr);
|
||||
|
||||
if (!n_ptr)
|
||||
n_ptr = node_create(l_ptr->addr);
|
||||
if (n_ptr) {
|
||||
u32 bearer_id = l_ptr->b_ptr->identity;
|
||||
char addr_string[16];
|
||||
|
||||
assert(bearer_id < MAX_BEARERS);
|
||||
if (n_ptr->link_cnt >= 2) {
|
||||
char addr_string[16];
|
||||
|
||||
err("Attempt to create third link to %s\n",
|
||||
addr_string_fill(addr_string, n_ptr->addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!n_ptr->links[bearer_id]) {
|
||||
n_ptr->links[bearer_id] = l_ptr;
|
||||
net.zones[tipc_zone(l_ptr->addr)]->links++;
|
||||
n_ptr->link_cnt++;
|
||||
return n_ptr;
|
||||
}
|
||||
err("Attempt to establish second link on <%s> to <%s> \n",
|
||||
l_ptr->b_ptr->publ.name,
|
||||
addr_string_fill(addr_string, l_ptr->addr));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void node_detach_link(struct node *n_ptr, struct link *l_ptr)
|
||||
{
|
||||
n_ptr->links[l_ptr->b_ptr->identity] = 0;
|
||||
net.zones[tipc_zone(l_ptr->addr)]->links--;
|
||||
n_ptr->link_cnt--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routing table management - five cases to handle:
|
||||
*
|
||||
* 1: A link towards a zone/cluster external node comes up.
|
||||
* => Send a multicast message updating routing tables of all
|
||||
* system nodes within own cluster that the new destination
|
||||
* can be reached via this node.
|
||||
* (node.establishedContact()=>cluster.multicastNewRoute())
|
||||
*
|
||||
* 2: A link towards a slave node comes up.
|
||||
* => Send a multicast message updating routing tables of all
|
||||
* system nodes within own cluster that the new destination
|
||||
* can be reached via this node.
|
||||
* (node.establishedContact()=>cluster.multicastNewRoute())
|
||||
* => Send a message to the slave node about existence
|
||||
* of all system nodes within cluster:
|
||||
* (node.establishedContact()=>cluster.sendLocalRoutes())
|
||||
*
|
||||
* 3: A new cluster local system node becomes available.
|
||||
* => Send message(s) to this particular node containing
|
||||
* information about all cluster external and slave
|
||||
* nodes which can be reached via this node.
|
||||
* (node.establishedContact()==>network.sendExternalRoutes())
|
||||
* (node.establishedContact()==>network.sendSlaveRoutes())
|
||||
* => Send messages to all directly connected slave nodes
|
||||
* containing information about the existence of the new node
|
||||
* (node.establishedContact()=>cluster.multicastNewRoute())
|
||||
*
|
||||
* 4: The link towards a zone/cluster external node or slave
|
||||
* node goes down.
|
||||
* => Send a multcast message updating routing tables of all
|
||||
* nodes within cluster that the new destination can not any
|
||||
* longer be reached via this node.
|
||||
* (node.lostAllLinks()=>cluster.bcastLostRoute())
|
||||
*
|
||||
* 5: A cluster local system node becomes unavailable.
|
||||
* => Remove all references to this node from the local
|
||||
* routing tables. Note: This is a completely node
|
||||
* local operation.
|
||||
* (node.lostAllLinks()=>network.removeAsRouter())
|
||||
* => Send messages to all directly connected slave nodes
|
||||
* containing information about loss of the node
|
||||
* (node.establishedContact()=>cluster.multicastLostRoute())
|
||||
*
|
||||
*/
|
||||
|
||||
static void node_established_contact(struct node *n_ptr)
|
||||
{
|
||||
struct cluster *c_ptr;
|
||||
|
||||
dbg("node_established_contact:-> %x\n", n_ptr->addr);
|
||||
if (!node_has_active_routes(n_ptr)) {
|
||||
k_signal((Handler)named_node_up, n_ptr->addr);
|
||||
}
|
||||
|
||||
/* Syncronize broadcast acks */
|
||||
n_ptr->bclink.acked = bclink_get_last_sent();
|
||||
|
||||
if (is_slave(tipc_own_addr))
|
||||
return;
|
||||
if (!in_own_cluster(n_ptr->addr)) {
|
||||
/* Usage case 1 (see above) */
|
||||
c_ptr = cluster_find(tipc_own_addr);
|
||||
if (!c_ptr)
|
||||
c_ptr = cluster_create(tipc_own_addr);
|
||||
if (c_ptr)
|
||||
cluster_bcast_new_route(c_ptr, n_ptr->addr, 1,
|
||||
tipc_max_nodes);
|
||||
return;
|
||||
}
|
||||
|
||||
c_ptr = n_ptr->owner;
|
||||
if (is_slave(n_ptr->addr)) {
|
||||
/* Usage case 2 (see above) */
|
||||
cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes);
|
||||
cluster_send_local_routes(c_ptr, n_ptr->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (n_ptr->bclink.supported) {
|
||||
nmap_add(&cluster_bcast_nodes, n_ptr->addr);
|
||||
if (n_ptr->addr < tipc_own_addr)
|
||||
tipc_own_tag++;
|
||||
}
|
||||
|
||||
/* Case 3 (see above) */
|
||||
net_send_external_routes(n_ptr->addr);
|
||||
cluster_send_slave_routes(c_ptr, n_ptr->addr);
|
||||
cluster_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE,
|
||||
highest_allowed_slave);
|
||||
}
|
||||
|
||||
static void node_lost_contact(struct node *n_ptr)
|
||||
{
|
||||
struct cluster *c_ptr;
|
||||
struct node_subscr *ns, *tns;
|
||||
char addr_string[16];
|
||||
u32 i;
|
||||
|
||||
/* Clean up broadcast reception remains */
|
||||
n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
|
||||
while (n_ptr->bclink.deferred_head) {
|
||||
struct sk_buff* buf = n_ptr->bclink.deferred_head;
|
||||
n_ptr->bclink.deferred_head = buf->next;
|
||||
buf_discard(buf);
|
||||
}
|
||||
if (n_ptr->bclink.defragm) {
|
||||
buf_discard(n_ptr->bclink.defragm);
|
||||
n_ptr->bclink.defragm = NULL;
|
||||
}
|
||||
if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) {
|
||||
bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
|
||||
}
|
||||
|
||||
/* Update routing tables */
|
||||
if (is_slave(tipc_own_addr)) {
|
||||
net_remove_as_router(n_ptr->addr);
|
||||
} else {
|
||||
if (!in_own_cluster(n_ptr->addr)) {
|
||||
/* Case 4 (see above) */
|
||||
c_ptr = cluster_find(tipc_own_addr);
|
||||
cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1,
|
||||
tipc_max_nodes);
|
||||
} else {
|
||||
/* Case 5 (see above) */
|
||||
c_ptr = cluster_find(n_ptr->addr);
|
||||
if (is_slave(n_ptr->addr)) {
|
||||
cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1,
|
||||
tipc_max_nodes);
|
||||
} else {
|
||||
if (n_ptr->bclink.supported) {
|
||||
nmap_remove(&cluster_bcast_nodes,
|
||||
n_ptr->addr);
|
||||
if (n_ptr->addr < tipc_own_addr)
|
||||
tipc_own_tag--;
|
||||
}
|
||||
net_remove_as_router(n_ptr->addr);
|
||||
cluster_bcast_lost_route(c_ptr, n_ptr->addr,
|
||||
LOWEST_SLAVE,
|
||||
highest_allowed_slave);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node_has_active_routes(n_ptr))
|
||||
return;
|
||||
|
||||
info("Lost contact with %s\n",
|
||||
addr_string_fill(addr_string, n_ptr->addr));
|
||||
|
||||
/* Abort link changeover */
|
||||
for (i = 0; i < MAX_BEARERS; i++) {
|
||||
struct link *l_ptr = n_ptr->links[i];
|
||||
if (!l_ptr)
|
||||
continue;
|
||||
l_ptr->reset_checkpoint = l_ptr->next_in_no;
|
||||
l_ptr->exp_msg_count = 0;
|
||||
link_reset_fragments(l_ptr);
|
||||
}
|
||||
|
||||
/* Notify subscribers */
|
||||
list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
|
||||
ns->node = 0;
|
||||
list_del_init(&ns->nodesub_list);
|
||||
k_signal((Handler)ns->handle_node_down,
|
||||
(unsigned long)ns->usr_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* node_select_next_hop - find the next-hop node for a message
|
||||
*
|
||||
* Called by when cluster local lookup has failed.
|
||||
*/
|
||||
|
||||
struct node *node_select_next_hop(u32 addr, u32 selector)
|
||||
{
|
||||
struct node *n_ptr;
|
||||
u32 router_addr;
|
||||
|
||||
if (!addr_domain_valid(addr))
|
||||
return 0;
|
||||
|
||||
/* Look for direct link to destination processsor */
|
||||
n_ptr = node_find(addr);
|
||||
if (n_ptr && node_has_active_links(n_ptr))
|
||||
return n_ptr;
|
||||
|
||||
/* Cluster local system nodes *must* have direct links */
|
||||
if (!is_slave(addr) && in_own_cluster(addr))
|
||||
return 0;
|
||||
|
||||
/* Look for cluster local router with direct link to node */
|
||||
router_addr = node_select_router(n_ptr, selector);
|
||||
if (router_addr)
|
||||
return node_select(router_addr, selector);
|
||||
|
||||
/* Slave nodes can only be accessed within own cluster via a
|
||||
known router with direct link -- if no router was found,give up */
|
||||
if (is_slave(addr))
|
||||
return 0;
|
||||
|
||||
/* Inter zone/cluster -- find any direct link to remote cluster */
|
||||
addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
|
||||
n_ptr = net_select_remote_node(addr, selector);
|
||||
if (n_ptr && node_has_active_links(n_ptr))
|
||||
return n_ptr;
|
||||
|
||||
/* Last resort -- look for any router to anywhere in remote zone */
|
||||
router_addr = net_select_router(addr, selector);
|
||||
if (router_addr)
|
||||
return node_select(router_addr, selector);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* node_select_router - select router to reach specified node
|
||||
*
|
||||
* Uses a deterministic and fair algorithm for selecting router node.
|
||||
*/
|
||||
|
||||
u32 node_select_router(struct node *n_ptr, u32 ref)
|
||||
{
|
||||
u32 ulim;
|
||||
u32 mask;
|
||||
u32 start;
|
||||
u32 r;
|
||||
|
||||
if (!n_ptr)
|
||||
return 0;
|
||||
|
||||
if (n_ptr->last_router < 0)
|
||||
return 0;
|
||||
ulim = ((n_ptr->last_router + 1) * 32) - 1;
|
||||
|
||||
/* Start entry must be random */
|
||||
mask = tipc_max_nodes;
|
||||
while (mask > ulim)
|
||||
mask >>= 1;
|
||||
start = ref & mask;
|
||||
r = start;
|
||||
|
||||
/* Lookup upwards with wrap-around */
|
||||
do {
|
||||
if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
|
||||
break;
|
||||
} while (++r <= ulim);
|
||||
if (r > ulim) {
|
||||
r = 1;
|
||||
do {
|
||||
if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
|
||||
break;
|
||||
} while (++r < start);
|
||||
assert(r != start);
|
||||
}
|
||||
assert(r && (r <= ulim));
|
||||
return tipc_addr(own_zone(), own_cluster(), r);
|
||||
}
|
||||
|
||||
void node_add_router(struct node *n_ptr, u32 router)
|
||||
{
|
||||
u32 r_num = tipc_node(router);
|
||||
|
||||
n_ptr->routers[r_num / 32] =
|
||||
((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]);
|
||||
n_ptr->last_router = tipc_max_nodes / 32;
|
||||
while ((--n_ptr->last_router >= 0) &&
|
||||
!n_ptr->routers[n_ptr->last_router]);
|
||||
}
|
||||
|
||||
void node_remove_router(struct node *n_ptr, u32 router)
|
||||
{
|
||||
u32 r_num = tipc_node(router);
|
||||
|
||||
if (n_ptr->last_router < 0)
|
||||
return; /* No routes */
|
||||
|
||||
n_ptr->routers[r_num / 32] =
|
||||
((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32]));
|
||||
n_ptr->last_router = tipc_max_nodes / 32;
|
||||
while ((--n_ptr->last_router >= 0) &&
|
||||
!n_ptr->routers[n_ptr->last_router]);
|
||||
|
||||
if (!node_is_up(n_ptr))
|
||||
node_lost_contact(n_ptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void node_print(struct print_buf *buf, struct node *n_ptr, char *str)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
tipc_printf(buf, "\n\n%s", str);
|
||||
for (i = 0; i < MAX_BEARERS; i++) {
|
||||
if (!n_ptr->links[i])
|
||||
continue;
|
||||
tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]);
|
||||
}
|
||||
tipc_printf(buf, "Active links: [%x,%x]\n",
|
||||
n_ptr->active_links[0], n_ptr->active_links[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
u32 tipc_available_nodes(const u32 domain)
|
||||
{
|
||||
struct node *n_ptr;
|
||||
u32 cnt = 0;
|
||||
|
||||
for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
|
||||
if (!in_scope(domain, n_ptr->addr))
|
||||
continue;
|
||||
if (node_is_up(n_ptr))
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space)
|
||||
{
|
||||
u32 domain;
|
||||
struct sk_buff *buf;
|
||||
struct node *n_ptr;
|
||||
struct tipc_node_info node_info;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
domain = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
domain = ntohl(domain);
|
||||
if (!addr_domain_valid(domain))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (network address)");
|
||||
|
||||
if (!nodes)
|
||||
return cfg_reply_none();
|
||||
|
||||
/* For now, get space for all other nodes
|
||||
(will need to modify this when slave nodes are supported */
|
||||
|
||||
buf = cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) *
|
||||
(tipc_max_nodes - 1));
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
/* Add TLVs for all nodes in scope */
|
||||
|
||||
for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
|
||||
if (!in_scope(domain, n_ptr->addr))
|
||||
continue;
|
||||
node_info.addr = htonl(n_ptr->addr);
|
||||
node_info.up = htonl(node_is_up(n_ptr));
|
||||
cfg_append_tlv(buf, TIPC_TLV_NODE_INFO,
|
||||
&node_info, sizeof(node_info));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space)
|
||||
{
|
||||
u32 domain;
|
||||
struct sk_buff *buf;
|
||||
struct node *n_ptr;
|
||||
struct tipc_link_info link_info;
|
||||
|
||||
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
|
||||
return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
|
||||
|
||||
domain = *(u32 *)TLV_DATA(req_tlv_area);
|
||||
domain = ntohl(domain);
|
||||
if (!addr_domain_valid(domain))
|
||||
return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (network address)");
|
||||
|
||||
if (!nodes)
|
||||
return cfg_reply_none();
|
||||
|
||||
/* For now, get space for 2 links to all other nodes + bcast link
|
||||
(will need to modify this when slave nodes are supported */
|
||||
|
||||
buf = cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) *
|
||||
(2 * (tipc_max_nodes - 1) + 1));
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
/* Add TLV for broadcast link */
|
||||
|
||||
link_info.dest = tipc_own_addr & 0xfffff00;
|
||||
link_info.dest = htonl(link_info.dest);
|
||||
link_info.up = htonl(1);
|
||||
sprintf(link_info.str, bc_link_name);
|
||||
cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
|
||||
|
||||
/* Add TLVs for any other links in scope */
|
||||
|
||||
for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
|
||||
u32 i;
|
||||
|
||||
if (!in_scope(domain, n_ptr->addr))
|
||||
continue;
|
||||
for (i = 0; i < MAX_BEARERS; i++) {
|
||||
if (!n_ptr->links[i])
|
||||
continue;
|
||||
link_info.dest = htonl(n_ptr->addr);
|
||||
link_info.up = htonl(link_is_up(n_ptr->links[i]));
|
||||
strcpy(link_info.str, n_ptr->links[i]->name);
|
||||
cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
|
||||
&link_info, sizeof(link_info));
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
141
net/tipc/node.h
Normal file
141
net/tipc/node.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* net/tipc/node.h: Include file for TIPC node management routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_NODE_H
|
||||
#define _TIPC_NODE_H
|
||||
|
||||
#include "node_subscr.h"
|
||||
#include "addr.h"
|
||||
#include "cluster.h"
|
||||
#include "bearer.h"
|
||||
|
||||
/**
|
||||
* struct node - TIPC node structure
|
||||
* @addr: network address of node
|
||||
* @lock: spinlock governing access to structure
|
||||
* @owner: pointer to cluster that node belongs to
|
||||
* @next: pointer to next node in sorted list of cluster's nodes
|
||||
* @nsub: list of "node down" subscriptions monitoring node
|
||||
* @active_links: pointers to active links to node
|
||||
* @links: pointers to all links to node
|
||||
* @link_cnt: number of links to node
|
||||
* @permit_changeover: non-zero if node has redundant links to this system
|
||||
* @routers: bitmap (used for multicluster communication)
|
||||
* @last_router: (used for multicluster communication)
|
||||
* @bclink: broadcast-related info
|
||||
* @supported: non-zero if node supports TIPC b'cast capability
|
||||
* @acked: sequence # of last outbound b'cast message acknowledged by node
|
||||
* @last_in: sequence # of last in-sequence b'cast message received from node
|
||||
* @gap_after: sequence # of last message not requiring a NAK request
|
||||
* @gap_to: sequence # of last message requiring a NAK request
|
||||
* @nack_sync: counter that determines when NAK requests should be sent
|
||||
* @deferred_head: oldest OOS b'cast message received from node
|
||||
* @deferred_tail: newest OOS b'cast message received from node
|
||||
* @defragm: list of partially reassembled b'cast message fragments from node
|
||||
*/
|
||||
|
||||
struct node {
|
||||
u32 addr;
|
||||
spinlock_t lock;
|
||||
struct cluster *owner;
|
||||
struct node *next;
|
||||
struct list_head nsub;
|
||||
struct link *active_links[2];
|
||||
struct link *links[MAX_BEARERS];
|
||||
int link_cnt;
|
||||
int permit_changeover;
|
||||
u32 routers[512/32];
|
||||
int last_router;
|
||||
struct {
|
||||
int supported;
|
||||
u32 acked;
|
||||
u32 last_in;
|
||||
u32 gap_after;
|
||||
u32 gap_to;
|
||||
u32 nack_sync;
|
||||
struct sk_buff *deferred_head;
|
||||
struct sk_buff *deferred_tail;
|
||||
struct sk_buff *defragm;
|
||||
} bclink;
|
||||
};
|
||||
|
||||
extern struct node *nodes;
|
||||
extern u32 tipc_own_tag;
|
||||
|
||||
struct node *node_create(u32 addr);
|
||||
void node_delete(struct node *n_ptr);
|
||||
struct node *node_attach_link(struct link *l_ptr);
|
||||
void node_detach_link(struct node *n_ptr, struct link *l_ptr);
|
||||
void node_link_down(struct node *n_ptr, struct link *l_ptr);
|
||||
void node_link_up(struct node *n_ptr, struct link *l_ptr);
|
||||
int node_has_active_links(struct node *n_ptr);
|
||||
int node_has_redundant_links(struct node *n_ptr);
|
||||
u32 node_select_router(struct node *n_ptr, u32 ref);
|
||||
struct node *node_select_next_hop(u32 addr, u32 selector);
|
||||
int node_is_up(struct node *n_ptr);
|
||||
void node_add_router(struct node *n_ptr, u32 router);
|
||||
void node_remove_router(struct node *n_ptr, u32 router);
|
||||
struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space);
|
||||
struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space);
|
||||
|
||||
static inline struct node *node_find(u32 addr)
|
||||
{
|
||||
if (likely(in_own_cluster(addr)))
|
||||
return local_nodes[tipc_node(addr)];
|
||||
else if (addr_domain_valid(addr)) {
|
||||
struct cluster *c_ptr = cluster_find(addr);
|
||||
|
||||
if (c_ptr)
|
||||
return c_ptr->nodes[tipc_node(addr)];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct node *node_select(u32 addr, u32 selector)
|
||||
{
|
||||
if (likely(in_own_cluster(addr)))
|
||||
return local_nodes[tipc_node(addr)];
|
||||
return node_select_next_hop(addr, selector);
|
||||
}
|
||||
|
||||
static inline void node_lock(struct node *n_ptr)
|
||||
{
|
||||
spin_lock_bh(&n_ptr->lock);
|
||||
}
|
||||
|
||||
static inline void node_unlock(struct node *n_ptr)
|
||||
{
|
||||
spin_unlock_bh(&n_ptr->lock);
|
||||
}
|
||||
|
||||
#endif
|
76
net/tipc/node_subscr.c
Normal file
76
net/tipc/node_subscr.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* net/tipc/node_subscr.c: TIPC "node down" subscription handling
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "dbg.h"
|
||||
#include "node_subscr.h"
|
||||
#include "node.h"
|
||||
#include "addr.h"
|
||||
|
||||
/**
|
||||
* nodesub_subscribe - create "node down" subscription for specified node
|
||||
*/
|
||||
|
||||
void nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
|
||||
void *usr_handle, net_ev_handler handle_down)
|
||||
{
|
||||
node_sub->node = 0;
|
||||
if (addr == tipc_own_addr)
|
||||
return;
|
||||
if (!addr_node_valid(addr)) {
|
||||
warn("node_subscr with illegal %x\n", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
node_sub->handle_node_down = handle_down;
|
||||
node_sub->usr_handle = usr_handle;
|
||||
node_sub->node = node_find(addr);
|
||||
assert(node_sub->node);
|
||||
node_lock(node_sub->node);
|
||||
list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub);
|
||||
node_unlock(node_sub->node);
|
||||
}
|
||||
|
||||
/**
|
||||
* nodesub_unsubscribe - cancel "node down" subscription (if any)
|
||||
*/
|
||||
|
||||
void nodesub_unsubscribe(struct node_subscr *node_sub)
|
||||
{
|
||||
if (!node_sub->node)
|
||||
return;
|
||||
|
||||
node_lock(node_sub->node);
|
||||
list_del_init(&node_sub->nodesub_list);
|
||||
node_unlock(node_sub->node);
|
||||
}
|
60
net/tipc/node_subscr.h
Normal file
60
net/tipc/node_subscr.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_NODE_SUBSCR_H
|
||||
#define _TIPC_NODE_SUBSCR_H
|
||||
|
||||
#include "addr.h"
|
||||
|
||||
typedef void (*net_ev_handler) (void *usr_handle);
|
||||
|
||||
/**
|
||||
* struct node_subscr - "node down" subscription entry
|
||||
* @node: ptr to node structure of interest (or NULL, if none)
|
||||
* @handle_node_down: routine to invoke when node fails
|
||||
* @usr_handle: argument to pass to routine when node fails
|
||||
* @nodesub_list: adjacent entries in list of subscriptions for the node
|
||||
*/
|
||||
|
||||
struct node_subscr {
|
||||
struct node *node;
|
||||
net_ev_handler handle_node_down;
|
||||
void *usr_handle;
|
||||
struct list_head nodesub_list;
|
||||
};
|
||||
|
||||
void nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
|
||||
void *usr_handle, net_ev_handler handle_down);
|
||||
void nodesub_unsubscribe(struct node_subscr *node_sub);
|
||||
|
||||
#endif
|
1704
net/tipc/port.c
Normal file
1704
net/tipc/port.c
Normal file
File diff suppressed because it is too large
Load diff
206
net/tipc/port.h
Normal file
206
net/tipc/port.h
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* net/tipc/port.h: Include file for TIPC port code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_PORT_H
|
||||
#define _TIPC_PORT_H
|
||||
|
||||
#include <net/tipc/tipc_port.h>
|
||||
#include "ref.h"
|
||||
#include "net.h"
|
||||
#include "msg.h"
|
||||
#include "dbg.h"
|
||||
#include "node_subscr.h"
|
||||
|
||||
/**
|
||||
* struct user_port - TIPC user port (used with native API)
|
||||
* @user_ref: id of user who created user port
|
||||
* @usr_handle: user-specified field
|
||||
* @ref: object reference to associated TIPC port
|
||||
* <various callback routines>
|
||||
* @uport_list: adjacent user ports in list of ports held by user
|
||||
*/
|
||||
|
||||
struct user_port {
|
||||
u32 user_ref;
|
||||
void *usr_handle;
|
||||
u32 ref;
|
||||
tipc_msg_err_event err_cb;
|
||||
tipc_named_msg_err_event named_err_cb;
|
||||
tipc_conn_shutdown_event conn_err_cb;
|
||||
tipc_msg_event msg_cb;
|
||||
tipc_named_msg_event named_msg_cb;
|
||||
tipc_conn_msg_event conn_msg_cb;
|
||||
tipc_continue_event continue_event_cb;
|
||||
struct list_head uport_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct port - TIPC port structure
|
||||
* @publ: TIPC port info available to privileged users
|
||||
* @port_list: adjacent ports in TIPC's global list of ports
|
||||
* @dispatcher: ptr to routine which handles received messages
|
||||
* @wakeup: ptr to routine to call when port is no longer congested
|
||||
* @user_port: ptr to user port associated with port (if any)
|
||||
* @wait_list: adjacent ports in list of ports waiting on link congestion
|
||||
* @congested_link: ptr to congested link port is waiting on
|
||||
* @waiting_pkts:
|
||||
* @sent:
|
||||
* @acked:
|
||||
* @publications: list of publications for port
|
||||
* @pub_count: total # of publications port has made during its lifetime
|
||||
* @max_pkt: maximum packet size "hint" used when building messages sent by port
|
||||
* @probing_state:
|
||||
* @probing_interval:
|
||||
* @last_in_seqno:
|
||||
* @timer_ref:
|
||||
* @subscription: "node down" subscription used to terminate failed connections
|
||||
*/
|
||||
|
||||
struct port {
|
||||
struct tipc_port publ;
|
||||
struct list_head port_list;
|
||||
u32 (*dispatcher)(struct tipc_port *, struct sk_buff *);
|
||||
void (*wakeup)(struct tipc_port *);
|
||||
struct user_port *user_port;
|
||||
struct list_head wait_list;
|
||||
struct link *congested_link;
|
||||
u32 waiting_pkts;
|
||||
u32 sent;
|
||||
u32 acked;
|
||||
struct list_head publications;
|
||||
u32 pub_count;
|
||||
u32 max_pkt;
|
||||
u32 probing_state;
|
||||
u32 probing_interval;
|
||||
u32 last_in_seqno;
|
||||
struct timer_list timer;
|
||||
struct node_subscr subscription;
|
||||
};
|
||||
|
||||
extern spinlock_t port_list_lock;
|
||||
struct port_list;
|
||||
|
||||
int port_recv_sections(struct port *p_ptr, u32 num_sect,
|
||||
struct iovec const *msg_sect);
|
||||
int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
|
||||
struct iovec const *msg_sect, u32 num_sect,
|
||||
int err);
|
||||
struct sk_buff *port_get_ports(void);
|
||||
struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space);
|
||||
void port_recv_proto_msg(struct sk_buff *buf);
|
||||
void port_recv_mcast(struct sk_buff *buf, struct port_list *dp);
|
||||
void port_reinit(void);
|
||||
|
||||
/**
|
||||
* port_lock - lock port instance referred to and return its pointer
|
||||
*/
|
||||
|
||||
static inline struct port *port_lock(u32 ref)
|
||||
{
|
||||
return (struct port *)ref_lock(ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* port_unlock - unlock a port instance
|
||||
*
|
||||
* Can use pointer instead of ref_unlock() since port is already locked.
|
||||
*/
|
||||
|
||||
static inline void port_unlock(struct port *p_ptr)
|
||||
{
|
||||
spin_unlock_bh(p_ptr->publ.lock);
|
||||
}
|
||||
|
||||
static inline struct port* port_deref(u32 ref)
|
||||
{
|
||||
return (struct port *)ref_deref(ref);
|
||||
}
|
||||
|
||||
static inline u32 peer_port(struct port *p_ptr)
|
||||
{
|
||||
return msg_destport(&p_ptr->publ.phdr);
|
||||
}
|
||||
|
||||
static inline u32 peer_node(struct port *p_ptr)
|
||||
{
|
||||
return msg_destnode(&p_ptr->publ.phdr);
|
||||
}
|
||||
|
||||
static inline int port_congested(struct port *p_ptr)
|
||||
{
|
||||
return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* port_recv_msg - receive message from lower layer and deliver to port user
|
||||
*/
|
||||
|
||||
static inline int port_recv_msg(struct sk_buff *buf)
|
||||
{
|
||||
struct port *p_ptr;
|
||||
struct tipc_msg *msg = buf_msg(buf);
|
||||
u32 destport = msg_destport(msg);
|
||||
u32 dsz = msg_data_sz(msg);
|
||||
u32 err;
|
||||
|
||||
/* forward unresolved named message */
|
||||
if (unlikely(!destport)) {
|
||||
net_route_msg(buf);
|
||||
return dsz;
|
||||
}
|
||||
|
||||
/* validate destination & pass to port, otherwise reject message */
|
||||
p_ptr = port_lock(destport);
|
||||
if (likely(p_ptr)) {
|
||||
if (likely(p_ptr->publ.connected)) {
|
||||
if ((unlikely(msg_origport(msg) != peer_port(p_ptr))) ||
|
||||
(unlikely(msg_orignode(msg) != peer_node(p_ptr))) ||
|
||||
(unlikely(!msg_connected(msg)))) {
|
||||
err = TIPC_ERR_NO_PORT;
|
||||
port_unlock(p_ptr);
|
||||
goto reject;
|
||||
}
|
||||
}
|
||||
err = p_ptr->dispatcher(&p_ptr->publ, buf);
|
||||
port_unlock(p_ptr);
|
||||
if (likely(!err))
|
||||
return dsz;
|
||||
} else {
|
||||
err = TIPC_ERR_NO_PORT;
|
||||
}
|
||||
reject:
|
||||
dbg("port->rejecting, err = %x..\n",err);
|
||||
return tipc_reject_msg(buf, err);
|
||||
}
|
||||
|
||||
#endif
|
186
net/tipc/ref.c
Normal file
186
net/tipc/ref.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* net/tipc/ref.c: TIPC object registry code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "ref.h"
|
||||
#include "port.h"
|
||||
#include "subscr.h"
|
||||
#include "name_distr.h"
|
||||
#include "name_table.h"
|
||||
#include "config.h"
|
||||
#include "discover.h"
|
||||
#include "bearer.h"
|
||||
#include "node.h"
|
||||
#include "bcast.h"
|
||||
|
||||
/*
|
||||
* Object reference table consists of 2**N entries.
|
||||
*
|
||||
* A used entry has object ptr != 0, reference == XXXX|own index
|
||||
* (XXXX changes each time entry is acquired)
|
||||
* A free entry has object ptr == 0, reference == YYYY|next free index
|
||||
* (YYYY is one more than last used XXXX)
|
||||
*
|
||||
* Free list is initially chained from entry (2**N)-1 to entry 1.
|
||||
* Entry 0 is not used to allow index 0 to indicate the end of the free list.
|
||||
*
|
||||
* Note: Any accidental reference of the form XXXX|0--0 won't match entry 0
|
||||
* because entry 0's reference field has the form XXXX|1--1.
|
||||
*/
|
||||
|
||||
struct ref_table ref_table = { 0 };
|
||||
|
||||
rwlock_t reftbl_lock = RW_LOCK_UNLOCKED;
|
||||
|
||||
/**
|
||||
* ref_table_init - create reference table for objects
|
||||
*/
|
||||
|
||||
int ref_table_init(u32 requested_size, u32 start)
|
||||
{
|
||||
struct reference *table;
|
||||
u32 sz = 1 << 4;
|
||||
u32 index_mask;
|
||||
int i;
|
||||
|
||||
while (sz < requested_size) {
|
||||
sz <<= 1;
|
||||
}
|
||||
table = (struct reference *)vmalloc(sz * sizeof(struct reference));
|
||||
if (table == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
write_lock_bh(&reftbl_lock);
|
||||
index_mask = sz - 1;
|
||||
for (i = sz - 1; i >= 0; i--) {
|
||||
table[i].object = 0;
|
||||
table[i].lock = SPIN_LOCK_UNLOCKED;
|
||||
table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
|
||||
}
|
||||
ref_table.entries = table;
|
||||
ref_table.index_mask = index_mask;
|
||||
ref_table.first_free = sz - 1;
|
||||
ref_table.last_free = 1;
|
||||
write_unlock_bh(&reftbl_lock);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* ref_table_stop - destroy reference table for objects
|
||||
*/
|
||||
|
||||
void ref_table_stop(void)
|
||||
{
|
||||
if (!ref_table.entries)
|
||||
return;
|
||||
|
||||
vfree(ref_table.entries);
|
||||
ref_table.entries = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ref_acquire - create reference to an object
|
||||
*
|
||||
* Return a unique reference value which can be translated back to the pointer
|
||||
* 'object' at a later time. Also, pass back a pointer to the lock protecting
|
||||
* the object, but without locking it.
|
||||
*/
|
||||
|
||||
u32 ref_acquire(void *object, spinlock_t **lock)
|
||||
{
|
||||
struct reference *entry;
|
||||
u32 index;
|
||||
u32 index_mask;
|
||||
u32 next_plus_upper;
|
||||
u32 reference = 0;
|
||||
|
||||
assert(ref_table.entries && object);
|
||||
|
||||
write_lock_bh(&reftbl_lock);
|
||||
if (ref_table.first_free) {
|
||||
index = ref_table.first_free;
|
||||
entry = &(ref_table.entries[index]);
|
||||
index_mask = ref_table.index_mask;
|
||||
/* take lock in case a previous user of entry still holds it */
|
||||
spin_lock_bh(&entry->lock);
|
||||
next_plus_upper = entry->data.next_plus_upper;
|
||||
ref_table.first_free = next_plus_upper & index_mask;
|
||||
reference = (next_plus_upper & ~index_mask) + index;
|
||||
entry->data.reference = reference;
|
||||
entry->object = object;
|
||||
if (lock != 0)
|
||||
*lock = &entry->lock;
|
||||
spin_unlock_bh(&entry->lock);
|
||||
}
|
||||
write_unlock_bh(&reftbl_lock);
|
||||
return reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* ref_discard - invalidate references to an object
|
||||
*
|
||||
* Disallow future references to an object and free up the entry for re-use.
|
||||
* Note: The entry's spin_lock may still be busy after discard
|
||||
*/
|
||||
|
||||
void ref_discard(u32 ref)
|
||||
{
|
||||
struct reference *entry;
|
||||
u32 index;
|
||||
u32 index_mask;
|
||||
|
||||
assert(ref_table.entries);
|
||||
assert(ref != 0);
|
||||
|
||||
write_lock_bh(&reftbl_lock);
|
||||
index_mask = ref_table.index_mask;
|
||||
index = ref & index_mask;
|
||||
entry = &(ref_table.entries[index]);
|
||||
assert(entry->object != 0);
|
||||
assert(entry->data.reference == ref);
|
||||
|
||||
/* mark entry as unused */
|
||||
entry->object = 0;
|
||||
if (ref_table.first_free == 0)
|
||||
ref_table.first_free = index;
|
||||
else
|
||||
/* next_plus_upper is always XXXX|0--0 for last free entry */
|
||||
ref_table.entries[ref_table.last_free].data.next_plus_upper
|
||||
|= index;
|
||||
ref_table.last_free = index;
|
||||
|
||||
/* increment upper bits of entry to invalidate subsequent references */
|
||||
entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
|
||||
write_unlock_bh(&reftbl_lock);
|
||||
}
|
||||
|
128
net/tipc/ref.h
Normal file
128
net/tipc/ref.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* net/tipc/ref.h: Include file for TIPC object registry code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_REF_H
|
||||
#define _TIPC_REF_H
|
||||
|
||||
/**
|
||||
* struct reference - TIPC object reference entry
|
||||
* @object: pointer to object associated with reference entry
|
||||
* @lock: spinlock controlling access to object
|
||||
* @data: reference value associated with object (or link to next unused entry)
|
||||
*/
|
||||
|
||||
struct reference {
|
||||
void *object;
|
||||
spinlock_t lock;
|
||||
union {
|
||||
u32 next_plus_upper;
|
||||
u32 reference;
|
||||
} data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ref_table - table of TIPC object reference entries
|
||||
* @entries: pointer to array of reference entries
|
||||
* @index_mask: bitmask for array index portion of reference values
|
||||
* @first_free: array index of first unused object reference entry
|
||||
* @last_free: array index of last unused object reference entry
|
||||
*/
|
||||
|
||||
struct ref_table {
|
||||
struct reference *entries;
|
||||
u32 index_mask;
|
||||
u32 first_free;
|
||||
u32 last_free;
|
||||
};
|
||||
|
||||
extern struct ref_table ref_table;
|
||||
|
||||
int ref_table_init(u32 requested_size, u32 start);
|
||||
void ref_table_stop(void);
|
||||
|
||||
u32 ref_acquire(void *object, spinlock_t **lock);
|
||||
void ref_discard(u32 ref);
|
||||
|
||||
|
||||
/**
|
||||
* ref_lock - lock referenced object and return pointer to it
|
||||
*/
|
||||
|
||||
static inline void *ref_lock(u32 ref)
|
||||
{
|
||||
if (likely(ref_table.entries)) {
|
||||
struct reference *r =
|
||||
&ref_table.entries[ref & ref_table.index_mask];
|
||||
|
||||
spin_lock_bh(&r->lock);
|
||||
if (likely(r->data.reference == ref))
|
||||
return r->object;
|
||||
spin_unlock_bh(&r->lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ref_unlock - unlock referenced object
|
||||
*/
|
||||
|
||||
static inline void ref_unlock(u32 ref)
|
||||
{
|
||||
if (likely(ref_table.entries)) {
|
||||
struct reference *r =
|
||||
&ref_table.entries[ref & ref_table.index_mask];
|
||||
|
||||
if (likely(r->data.reference == ref))
|
||||
spin_unlock_bh(&r->lock);
|
||||
else
|
||||
err("ref_unlock() invoked using obsolete reference\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ref_deref - return pointer referenced object (without locking it)
|
||||
*/
|
||||
|
||||
static inline void *ref_deref(u32 ref)
|
||||
{
|
||||
if (likely(ref_table.entries)) {
|
||||
struct reference *r =
|
||||
&ref_table.entries[ref & ref_table.index_mask];
|
||||
|
||||
if (likely(r->data.reference == ref))
|
||||
return r->object;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
1722
net/tipc/socket.c
Normal file
1722
net/tipc/socket.c
Normal file
File diff suppressed because it is too large
Load diff
522
net/tipc/subscr.c
Normal file
522
net/tipc/subscr.c
Normal file
|
@ -0,0 +1,522 @@
|
|||
/*
|
||||
* net/tipc/subscr.c: TIPC subscription service
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "dbg.h"
|
||||
#include "subscr.h"
|
||||
#include "name_table.h"
|
||||
#include "ref.h"
|
||||
|
||||
/**
|
||||
* struct subscriber - TIPC network topology subscriber
|
||||
* @ref: object reference to subscriber object itself
|
||||
* @lock: pointer to spinlock controlling access to subscriber object
|
||||
* @subscriber_list: adjacent subscribers in top. server's list of subscribers
|
||||
* @subscription_list: list of subscription objects for this subscriber
|
||||
* @port_ref: object reference to port used to communicate with subscriber
|
||||
* @swap: indicates if subscriber uses opposite endianness in its messages
|
||||
*/
|
||||
|
||||
struct subscriber {
|
||||
u32 ref;
|
||||
spinlock_t *lock;
|
||||
struct list_head subscriber_list;
|
||||
struct list_head subscription_list;
|
||||
u32 port_ref;
|
||||
int swap;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct top_srv - TIPC network topology subscription service
|
||||
* @user_ref: TIPC userid of subscription service
|
||||
* @setup_port: reference to TIPC port that handles subscription requests
|
||||
* @subscription_count: number of active subscriptions (not subscribers!)
|
||||
* @subscriber_list: list of ports subscribing to service
|
||||
* @lock: spinlock govering access to subscriber list
|
||||
*/
|
||||
|
||||
struct top_srv {
|
||||
u32 user_ref;
|
||||
u32 setup_port;
|
||||
atomic_t subscription_count;
|
||||
struct list_head subscriber_list;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct top_srv topsrv = { 0 };
|
||||
|
||||
/**
|
||||
* htohl - convert value to endianness used by destination
|
||||
* @in: value to convert
|
||||
* @swap: non-zero if endianness must be reversed
|
||||
*
|
||||
* Returns converted value
|
||||
*/
|
||||
|
||||
static inline u32 htohl(u32 in, int swap)
|
||||
{
|
||||
char *c = (char *)∈
|
||||
|
||||
return swap ? ((c[3] << 3) + (c[2] << 2) + (c[1] << 1) + c[0]) : in;
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_send_event - send a message containing a tipc_event to the subscriber
|
||||
*/
|
||||
|
||||
static void subscr_send_event(struct subscription *sub,
|
||||
u32 found_lower,
|
||||
u32 found_upper,
|
||||
u32 event,
|
||||
u32 port_ref,
|
||||
u32 node)
|
||||
{
|
||||
struct iovec msg_sect;
|
||||
|
||||
msg_sect.iov_base = (void *)&sub->evt;
|
||||
msg_sect.iov_len = sizeof(struct tipc_event);
|
||||
|
||||
sub->evt.event = htohl(event, sub->owner->swap);
|
||||
sub->evt.found_lower = htohl(found_lower, sub->owner->swap);
|
||||
sub->evt.found_upper = htohl(found_upper, sub->owner->swap);
|
||||
sub->evt.port.ref = htohl(port_ref, sub->owner->swap);
|
||||
sub->evt.port.node = htohl(node, sub->owner->swap);
|
||||
tipc_send(sub->owner->port_ref, 1, &msg_sect);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_overlap - test for subscription overlap with the given values
|
||||
*
|
||||
* Returns 1 if there is overlap, otherwise 0.
|
||||
*/
|
||||
|
||||
int subscr_overlap(struct subscription *sub,
|
||||
u32 found_lower,
|
||||
u32 found_upper)
|
||||
|
||||
{
|
||||
if (found_lower < sub->seq.lower)
|
||||
found_lower = sub->seq.lower;
|
||||
if (found_upper > sub->seq.upper)
|
||||
found_upper = sub->seq.upper;
|
||||
if (found_lower > found_upper)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_report_overlap - issue event if there is subscription overlap
|
||||
*
|
||||
* Protected by nameseq.lock in name_table.c
|
||||
*/
|
||||
|
||||
void subscr_report_overlap(struct subscription *sub,
|
||||
u32 found_lower,
|
||||
u32 found_upper,
|
||||
u32 event,
|
||||
u32 port_ref,
|
||||
u32 node,
|
||||
int must)
|
||||
{
|
||||
dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower,
|
||||
sub->seq.upper, found_lower, found_upper);
|
||||
if (!subscr_overlap(sub, found_lower, found_upper))
|
||||
return;
|
||||
if (!must && (sub->filter != TIPC_SUB_PORTS))
|
||||
return;
|
||||
subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_timeout - subscription timeout has occurred
|
||||
*/
|
||||
|
||||
static void subscr_timeout(struct subscription *sub)
|
||||
{
|
||||
struct subscriber *subscriber;
|
||||
u32 subscriber_ref;
|
||||
|
||||
/* Validate subscriber reference (in case subscriber is terminating) */
|
||||
|
||||
subscriber_ref = sub->owner->ref;
|
||||
subscriber = (struct subscriber *)ref_lock(subscriber_ref);
|
||||
if (subscriber == NULL)
|
||||
return;
|
||||
|
||||
/* Unlink subscription from name table */
|
||||
|
||||
nametbl_unsubscribe(sub);
|
||||
|
||||
/* Notify subscriber of timeout, then unlink subscription */
|
||||
|
||||
subscr_send_event(sub,
|
||||
sub->evt.s.seq.lower,
|
||||
sub->evt.s.seq.upper,
|
||||
TIPC_SUBSCR_TIMEOUT,
|
||||
0,
|
||||
0);
|
||||
list_del(&sub->subscription_list);
|
||||
|
||||
/* Now destroy subscription */
|
||||
|
||||
ref_unlock(subscriber_ref);
|
||||
k_term_timer(&sub->timer);
|
||||
kfree(sub);
|
||||
atomic_dec(&topsrv.subscription_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_terminate - terminate communication with a subscriber
|
||||
*
|
||||
* Called with subscriber locked. Routine must temporarily release this lock
|
||||
* to enable subscription timeout routine(s) to finish without deadlocking;
|
||||
* the lock is then reclaimed to allow caller to release it upon return.
|
||||
* (This should work even in the unlikely event some other thread creates
|
||||
* a new object reference in the interim that uses this lock; this routine will
|
||||
* simply wait for it to be released, then claim it.)
|
||||
*/
|
||||
|
||||
static void subscr_terminate(struct subscriber *subscriber)
|
||||
{
|
||||
struct subscription *sub;
|
||||
struct subscription *sub_temp;
|
||||
|
||||
/* Invalidate subscriber reference */
|
||||
|
||||
ref_discard(subscriber->ref);
|
||||
spin_unlock_bh(subscriber->lock);
|
||||
|
||||
/* Destroy any existing subscriptions for subscriber */
|
||||
|
||||
list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
|
||||
subscription_list) {
|
||||
if (sub->timeout != TIPC_WAIT_FOREVER) {
|
||||
k_cancel_timer(&sub->timer);
|
||||
k_term_timer(&sub->timer);
|
||||
}
|
||||
nametbl_unsubscribe(sub);
|
||||
list_del(&sub->subscription_list);
|
||||
dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
|
||||
sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
|
||||
kfree(sub);
|
||||
atomic_dec(&topsrv.subscription_count);
|
||||
}
|
||||
|
||||
/* Sever connection to subscriber */
|
||||
|
||||
tipc_shutdown(subscriber->port_ref);
|
||||
tipc_deleteport(subscriber->port_ref);
|
||||
|
||||
/* Remove subscriber from topology server's subscriber list */
|
||||
|
||||
spin_lock_bh(&topsrv.lock);
|
||||
list_del(&subscriber->subscriber_list);
|
||||
spin_unlock_bh(&topsrv.lock);
|
||||
|
||||
/* Now destroy subscriber */
|
||||
|
||||
spin_lock_bh(subscriber->lock);
|
||||
kfree(subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_subscribe - create subscription for subscriber
|
||||
*
|
||||
* Called with subscriber locked
|
||||
*/
|
||||
|
||||
static void subscr_subscribe(struct tipc_subscr *s,
|
||||
struct subscriber *subscriber)
|
||||
{
|
||||
struct subscription *sub;
|
||||
|
||||
/* Refuse subscription if global limit exceeded */
|
||||
|
||||
if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
|
||||
warn("Failed: max %u subscriptions\n", tipc_max_subscriptions);
|
||||
subscr_terminate(subscriber);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate subscription object */
|
||||
|
||||
sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
|
||||
if (sub == NULL) {
|
||||
warn("Memory squeeze; ignoring subscription\n");
|
||||
subscr_terminate(subscriber);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine/update subscriber's endianness */
|
||||
|
||||
if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE))
|
||||
subscriber->swap = 0;
|
||||
else
|
||||
subscriber->swap = 1;
|
||||
|
||||
/* Initialize subscription object */
|
||||
|
||||
memset(sub, 0, sizeof(*sub));
|
||||
sub->seq.type = htohl(s->seq.type, subscriber->swap);
|
||||
sub->seq.lower = htohl(s->seq.lower, subscriber->swap);
|
||||
sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
|
||||
sub->timeout = htohl(s->timeout, subscriber->swap);
|
||||
sub->filter = htohl(s->filter, subscriber->swap);
|
||||
if ((((sub->filter != TIPC_SUB_PORTS)
|
||||
&& (sub->filter != TIPC_SUB_SERVICE)))
|
||||
|| (sub->seq.lower > sub->seq.upper)) {
|
||||
warn("Rejecting illegal subscription %u,%u,%u\n",
|
||||
sub->seq.type, sub->seq.lower, sub->seq.upper);
|
||||
kfree(sub);
|
||||
subscr_terminate(subscriber);
|
||||
return;
|
||||
}
|
||||
memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr));
|
||||
INIT_LIST_HEAD(&sub->subscription_list);
|
||||
INIT_LIST_HEAD(&sub->nameseq_list);
|
||||
list_add(&sub->subscription_list, &subscriber->subscription_list);
|
||||
atomic_inc(&topsrv.subscription_count);
|
||||
if (sub->timeout != TIPC_WAIT_FOREVER) {
|
||||
k_init_timer(&sub->timer,
|
||||
(Handler)subscr_timeout, (unsigned long)sub);
|
||||
k_start_timer(&sub->timer, sub->timeout);
|
||||
}
|
||||
sub->owner = subscriber;
|
||||
nametbl_subscribe(sub);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_conn_shutdown_event - handle termination request from subscriber
|
||||
*/
|
||||
|
||||
static void subscr_conn_shutdown_event(void *usr_handle,
|
||||
u32 portref,
|
||||
struct sk_buff **buf,
|
||||
unsigned char const *data,
|
||||
unsigned int size,
|
||||
int reason)
|
||||
{
|
||||
struct subscriber *subscriber = ref_lock((u32)usr_handle);
|
||||
spinlock_t *subscriber_lock;
|
||||
|
||||
if (subscriber == NULL)
|
||||
return;
|
||||
|
||||
subscriber_lock = subscriber->lock;
|
||||
subscr_terminate(subscriber);
|
||||
spin_unlock_bh(subscriber_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_conn_msg_event - handle new subscription request from subscriber
|
||||
*/
|
||||
|
||||
static void subscr_conn_msg_event(void *usr_handle,
|
||||
u32 port_ref,
|
||||
struct sk_buff **buf,
|
||||
const unchar *data,
|
||||
u32 size)
|
||||
{
|
||||
struct subscriber *subscriber = ref_lock((u32)usr_handle);
|
||||
spinlock_t *subscriber_lock;
|
||||
|
||||
if (subscriber == NULL)
|
||||
return;
|
||||
|
||||
subscriber_lock = subscriber->lock;
|
||||
if (size != sizeof(struct tipc_subscr))
|
||||
subscr_terminate(subscriber);
|
||||
else
|
||||
subscr_subscribe((struct tipc_subscr *)data, subscriber);
|
||||
|
||||
spin_unlock_bh(subscriber_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_named_msg_event - handle request to establish a new subscriber
|
||||
*/
|
||||
|
||||
static void subscr_named_msg_event(void *usr_handle,
|
||||
u32 port_ref,
|
||||
struct sk_buff **buf,
|
||||
const unchar *data,
|
||||
u32 size,
|
||||
u32 importance,
|
||||
struct tipc_portid const *orig,
|
||||
struct tipc_name_seq const *dest)
|
||||
{
|
||||
struct subscriber *subscriber;
|
||||
struct iovec msg_sect = {0, 0};
|
||||
spinlock_t *subscriber_lock;
|
||||
|
||||
dbg("subscr_named_msg_event: orig = %x own = %x,\n",
|
||||
orig->node, tipc_own_addr);
|
||||
if (size && (size != sizeof(struct tipc_subscr))) {
|
||||
warn("Received tipc_subscr of invalid size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create subscriber object */
|
||||
|
||||
subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC);
|
||||
if (subscriber == NULL) {
|
||||
warn("Memory squeeze; ignoring subscriber setup\n");
|
||||
return;
|
||||
}
|
||||
memset(subscriber, 0, sizeof(struct subscriber));
|
||||
INIT_LIST_HEAD(&subscriber->subscription_list);
|
||||
INIT_LIST_HEAD(&subscriber->subscriber_list);
|
||||
subscriber->ref = ref_acquire(subscriber, &subscriber->lock);
|
||||
if (subscriber->ref == 0) {
|
||||
warn("Failed to acquire subscriber reference\n");
|
||||
kfree(subscriber);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Establish a connection to subscriber */
|
||||
|
||||
tipc_createport(topsrv.user_ref,
|
||||
(void *)subscriber->ref,
|
||||
importance,
|
||||
0,
|
||||
0,
|
||||
subscr_conn_shutdown_event,
|
||||
0,
|
||||
0,
|
||||
subscr_conn_msg_event,
|
||||
0,
|
||||
&subscriber->port_ref);
|
||||
if (subscriber->port_ref == 0) {
|
||||
warn("Memory squeeze; failed to create subscription port\n");
|
||||
ref_discard(subscriber->ref);
|
||||
kfree(subscriber);
|
||||
return;
|
||||
}
|
||||
tipc_connect2port(subscriber->port_ref, orig);
|
||||
|
||||
|
||||
/* Add subscriber to topology server's subscriber list */
|
||||
|
||||
ref_lock(subscriber->ref);
|
||||
spin_lock_bh(&topsrv.lock);
|
||||
list_add(&subscriber->subscriber_list, &topsrv.subscriber_list);
|
||||
spin_unlock_bh(&topsrv.lock);
|
||||
|
||||
/*
|
||||
* Subscribe now if message contains a subscription,
|
||||
* otherwise send an empty response to complete connection handshaking
|
||||
*/
|
||||
|
||||
subscriber_lock = subscriber->lock;
|
||||
if (size)
|
||||
subscr_subscribe((struct tipc_subscr *)data, subscriber);
|
||||
else
|
||||
tipc_send(subscriber->port_ref, 1, &msg_sect);
|
||||
|
||||
spin_unlock_bh(subscriber_lock);
|
||||
}
|
||||
|
||||
int subscr_start(void)
|
||||
{
|
||||
struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV};
|
||||
int res = -1;
|
||||
|
||||
memset(&topsrv, 0, sizeof (topsrv));
|
||||
topsrv.lock = SPIN_LOCK_UNLOCKED;
|
||||
INIT_LIST_HEAD(&topsrv.subscriber_list);
|
||||
|
||||
spin_lock_bh(&topsrv.lock);
|
||||
res = tipc_attach(&topsrv.user_ref, 0, 0);
|
||||
if (res) {
|
||||
spin_unlock_bh(&topsrv.lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = tipc_createport(topsrv.user_ref,
|
||||
0,
|
||||
TIPC_CRITICAL_IMPORTANCE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
subscr_named_msg_event,
|
||||
0,
|
||||
0,
|
||||
&topsrv.setup_port);
|
||||
if (res)
|
||||
goto failed;
|
||||
|
||||
res = nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
|
||||
if (res)
|
||||
goto failed;
|
||||
|
||||
spin_unlock_bh(&topsrv.lock);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
err("Unable to create subscription service\n");
|
||||
tipc_detach(topsrv.user_ref);
|
||||
topsrv.user_ref = 0;
|
||||
spin_unlock_bh(&topsrv.lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
void subscr_stop(void)
|
||||
{
|
||||
struct subscriber *subscriber;
|
||||
struct subscriber *subscriber_temp;
|
||||
spinlock_t *subscriber_lock;
|
||||
|
||||
if (topsrv.user_ref) {
|
||||
tipc_deleteport(topsrv.setup_port);
|
||||
list_for_each_entry_safe(subscriber, subscriber_temp,
|
||||
&topsrv.subscriber_list,
|
||||
subscriber_list) {
|
||||
ref_lock(subscriber->ref);
|
||||
subscriber_lock = subscriber->lock;
|
||||
subscr_terminate(subscriber);
|
||||
spin_unlock_bh(subscriber_lock);
|
||||
}
|
||||
tipc_detach(topsrv.user_ref);
|
||||
topsrv.user_ref = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int tipc_ispublished(struct tipc_name const *name)
|
||||
{
|
||||
u32 domain = 0;
|
||||
|
||||
return(nametbl_translate(name->type, name->instance,&domain) != 0);
|
||||
}
|
||||
|
77
net/tipc/subscr.h
Normal file
77
net/tipc/subscr.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* net/tipc/subscr.h: Include file for TIPC subscription service
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_SUBSCR_H
|
||||
#define _TIPC_SUBSCR_H
|
||||
|
||||
/**
|
||||
* struct subscription - TIPC network topology subscription object
|
||||
* @seq: name sequence associated with subscription
|
||||
* @timeout: duration of subscription (in ms)
|
||||
* @filter: event filtering to be done for subscription
|
||||
* @evt: template for events generated by subscription
|
||||
* @subscription_list: adjacent subscriptions in subscriber's subscription list
|
||||
* @nameseq_list: adjacent subscriptions in name sequence's subscription list
|
||||
* @timer_ref: reference to timer governing subscription duration (may be NULL)
|
||||
* @owner: pointer to subscriber object associated with this subscription
|
||||
*/
|
||||
|
||||
struct subscription {
|
||||
struct tipc_name_seq seq;
|
||||
u32 timeout;
|
||||
u32 filter;
|
||||
struct tipc_event evt;
|
||||
struct list_head subscription_list;
|
||||
struct list_head nameseq_list;
|
||||
struct timer_list timer;
|
||||
struct subscriber *owner;
|
||||
};
|
||||
|
||||
int subscr_overlap(struct subscription * sub,
|
||||
u32 found_lower,
|
||||
u32 found_upper);
|
||||
|
||||
void subscr_report_overlap(struct subscription * sub,
|
||||
u32 found_lower,
|
||||
u32 found_upper,
|
||||
u32 event,
|
||||
u32 port_ref,
|
||||
u32 node,
|
||||
int must_report);
|
||||
|
||||
int subscr_start(void);
|
||||
|
||||
void subscr_stop(void);
|
||||
|
||||
|
||||
#endif
|
262
net/tipc/user_reg.c
Normal file
262
net/tipc/user_reg.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* net/tipc/user_reg.c: TIPC user registry code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "user_reg.h"
|
||||
|
||||
/*
|
||||
* TIPC user registry keeps track of users of the tipc_port interface.
|
||||
*
|
||||
* The registry utilizes an array of "TIPC user" entries;
|
||||
* a user's ID is the index of their associated array entry.
|
||||
* Array entry 0 is not used, so userid 0 is not valid;
|
||||
* TIPC sometimes uses this value to denote an anonymous user.
|
||||
* The list of free entries is initially chained from last entry to entry 1.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct tipc_user - registered TIPC user info
|
||||
* @next: index of next free registry entry (or -1 for an allocated entry)
|
||||
* @callback: ptr to routine to call when TIPC mode changes (NULL if none)
|
||||
* @usr_handle: user-defined value passed to callback routine
|
||||
* @ports: list of user ports owned by the user
|
||||
*/
|
||||
|
||||
struct tipc_user {
|
||||
int next;
|
||||
tipc_mode_event callback;
|
||||
void *usr_handle;
|
||||
struct list_head ports;
|
||||
};
|
||||
|
||||
#define MAX_USERID 64
|
||||
#define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user))
|
||||
|
||||
static struct tipc_user *users = 0;
|
||||
static u32 next_free_user = MAX_USERID + 1;
|
||||
static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
/**
|
||||
* reg_init - create TIPC user registry (but don't activate it)
|
||||
*
|
||||
* If registry has been pre-initialized it is left "as is".
|
||||
* NOTE: This routine may be called when TIPC is inactive.
|
||||
*/
|
||||
|
||||
static int reg_init(void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
spin_lock_bh(®_lock);
|
||||
if (!users) {
|
||||
users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC);
|
||||
if (users) {
|
||||
memset(users, 0, USER_LIST_SIZE);
|
||||
for (i = 1; i <= MAX_USERID; i++) {
|
||||
users[i].next = i - 1;
|
||||
}
|
||||
next_free_user = MAX_USERID;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(®_lock);
|
||||
return users ? TIPC_OK : -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* reg_callback - inform TIPC user about current operating mode
|
||||
*/
|
||||
|
||||
static void reg_callback(struct tipc_user *user_ptr)
|
||||
{
|
||||
tipc_mode_event cb;
|
||||
void *arg;
|
||||
|
||||
spin_lock_bh(®_lock);
|
||||
cb = user_ptr->callback;
|
||||
arg = user_ptr->usr_handle;
|
||||
spin_unlock_bh(®_lock);
|
||||
|
||||
if (cb)
|
||||
cb(arg, tipc_mode, tipc_own_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* reg_start - activate TIPC user registry
|
||||
*/
|
||||
|
||||
int reg_start(void)
|
||||
{
|
||||
u32 u;
|
||||
int res;
|
||||
|
||||
if ((res = reg_init()))
|
||||
return res;
|
||||
|
||||
for (u = 1; u <= MAX_USERID; u++) {
|
||||
if (users[u].callback)
|
||||
k_signal((Handler)reg_callback,
|
||||
(unsigned long)&users[u]);
|
||||
}
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* reg_stop - shut down & delete TIPC user registry
|
||||
*/
|
||||
|
||||
void reg_stop(void)
|
||||
{
|
||||
int id;
|
||||
|
||||
if (!users)
|
||||
return;
|
||||
|
||||
for (id = 1; id <= MAX_USERID; id++) {
|
||||
if (users[id].callback)
|
||||
reg_callback(&users[id]);
|
||||
}
|
||||
kfree(users);
|
||||
users = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_attach - register a TIPC user
|
||||
*
|
||||
* NOTE: This routine may be called when TIPC is inactive.
|
||||
*/
|
||||
|
||||
int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle)
|
||||
{
|
||||
struct tipc_user *user_ptr;
|
||||
|
||||
if ((tipc_mode == TIPC_NOT_RUNNING) && !cb)
|
||||
return -ENOPROTOOPT;
|
||||
if (!users)
|
||||
reg_init();
|
||||
|
||||
spin_lock_bh(®_lock);
|
||||
if (!next_free_user) {
|
||||
spin_unlock_bh(®_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
user_ptr = &users[next_free_user];
|
||||
*userid = next_free_user;
|
||||
next_free_user = user_ptr->next;
|
||||
user_ptr->next = -1;
|
||||
spin_unlock_bh(®_lock);
|
||||
|
||||
user_ptr->callback = cb;
|
||||
user_ptr->usr_handle = usr_handle;
|
||||
INIT_LIST_HEAD(&user_ptr->ports);
|
||||
atomic_inc(&tipc_user_count);
|
||||
|
||||
if (cb && (tipc_mode != TIPC_NOT_RUNNING))
|
||||
k_signal((Handler)reg_callback, (unsigned long)user_ptr);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_detach - deregister a TIPC user
|
||||
*/
|
||||
|
||||
void tipc_detach(u32 userid)
|
||||
{
|
||||
struct tipc_user *user_ptr;
|
||||
struct list_head ports_temp;
|
||||
struct user_port *up_ptr, *temp_up_ptr;
|
||||
|
||||
if ((userid == 0) || (userid > MAX_USERID))
|
||||
return;
|
||||
|
||||
spin_lock_bh(®_lock);
|
||||
if ((!users) || (users[userid].next >= 0)) {
|
||||
spin_unlock_bh(®_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
user_ptr = &users[userid];
|
||||
user_ptr->callback = NULL;
|
||||
INIT_LIST_HEAD(&ports_temp);
|
||||
list_splice(&user_ptr->ports, &ports_temp);
|
||||
user_ptr->next = next_free_user;
|
||||
next_free_user = userid;
|
||||
spin_unlock_bh(®_lock);
|
||||
|
||||
atomic_dec(&tipc_user_count);
|
||||
|
||||
list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) {
|
||||
tipc_deleteport(up_ptr->ref);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* reg_add_port - register a user's driver port
|
||||
*/
|
||||
|
||||
int reg_add_port(struct user_port *up_ptr)
|
||||
{
|
||||
struct tipc_user *user_ptr;
|
||||
|
||||
if (up_ptr->user_ref == 0)
|
||||
return TIPC_OK;
|
||||
if (up_ptr->user_ref > MAX_USERID)
|
||||
return -EINVAL;
|
||||
if ((tipc_mode == TIPC_NOT_RUNNING) || !users )
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
spin_lock_bh(®_lock);
|
||||
user_ptr = &users[up_ptr->user_ref];
|
||||
list_add(&up_ptr->uport_list, &user_ptr->ports);
|
||||
spin_unlock_bh(®_lock);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* reg_remove_port - deregister a user's driver port
|
||||
*/
|
||||
|
||||
int reg_remove_port(struct user_port *up_ptr)
|
||||
{
|
||||
if (up_ptr->user_ref == 0)
|
||||
return TIPC_OK;
|
||||
if (up_ptr->user_ref > MAX_USERID)
|
||||
return -EINVAL;
|
||||
if (!users )
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
spin_lock_bh(®_lock);
|
||||
list_del_init(&up_ptr->uport_list);
|
||||
spin_unlock_bh(®_lock);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
45
net/tipc/user_reg.h
Normal file
45
net/tipc/user_reg.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* net/tipc/user_reg.h: Include file for TIPC user registry code
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_USER_REG_H
|
||||
#define _TIPC_USER_REG_H
|
||||
|
||||
#include "port.h"
|
||||
|
||||
int reg_start(void);
|
||||
void reg_stop(void);
|
||||
|
||||
int reg_add_port(struct user_port *up_ptr);
|
||||
int reg_remove_port(struct user_port *up_ptr);
|
||||
|
||||
#endif
|
166
net/tipc/zone.c
Normal file
166
net/tipc/zone.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* net/tipc/zone.c: TIPC zone management routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "zone.h"
|
||||
#include "net.h"
|
||||
#include "addr.h"
|
||||
#include "node_subscr.h"
|
||||
#include "cluster.h"
|
||||
#include "node.h"
|
||||
|
||||
struct _zone *zone_create(u32 addr)
|
||||
{
|
||||
struct _zone *z_ptr = 0;
|
||||
u32 z_num;
|
||||
|
||||
if (!addr_domain_valid(addr))
|
||||
return 0;
|
||||
|
||||
z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
|
||||
if (z_ptr != NULL) {
|
||||
memset(z_ptr, 0, sizeof(*z_ptr));
|
||||
z_num = tipc_zone(addr);
|
||||
z_ptr->addr = tipc_addr(z_num, 0, 0);
|
||||
net.zones[z_num] = z_ptr;
|
||||
}
|
||||
return z_ptr;
|
||||
}
|
||||
|
||||
void zone_delete(struct _zone *z_ptr)
|
||||
{
|
||||
u32 c_num;
|
||||
|
||||
if (!z_ptr)
|
||||
return;
|
||||
for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
|
||||
cluster_delete(z_ptr->clusters[c_num]);
|
||||
}
|
||||
kfree(z_ptr);
|
||||
}
|
||||
|
||||
void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr)
|
||||
{
|
||||
u32 c_num = tipc_cluster(c_ptr->addr);
|
||||
|
||||
assert(c_ptr->addr);
|
||||
assert(c_num <= tipc_max_clusters);
|
||||
assert(z_ptr->clusters[c_num] == 0);
|
||||
z_ptr->clusters[c_num] = c_ptr;
|
||||
}
|
||||
|
||||
void zone_remove_as_router(struct _zone *z_ptr, u32 router)
|
||||
{
|
||||
u32 c_num;
|
||||
|
||||
for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
|
||||
if (z_ptr->clusters[c_num]) {
|
||||
cluster_remove_as_router(z_ptr->clusters[c_num],
|
||||
router);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void zone_send_external_routes(struct _zone *z_ptr, u32 dest)
|
||||
{
|
||||
u32 c_num;
|
||||
|
||||
for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
|
||||
if (z_ptr->clusters[c_num]) {
|
||||
if (in_own_cluster(z_ptr->addr))
|
||||
continue;
|
||||
cluster_send_ext_routes(z_ptr->clusters[c_num], dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref)
|
||||
{
|
||||
struct cluster *c_ptr;
|
||||
struct node *n_ptr;
|
||||
u32 c_num;
|
||||
|
||||
if (!z_ptr)
|
||||
return 0;
|
||||
c_ptr = z_ptr->clusters[tipc_cluster(addr)];
|
||||
if (!c_ptr)
|
||||
return 0;
|
||||
n_ptr = cluster_select_node(c_ptr, ref);
|
||||
if (n_ptr)
|
||||
return n_ptr;
|
||||
|
||||
/* Links to any other clusters within this zone ? */
|
||||
for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
|
||||
c_ptr = z_ptr->clusters[c_num];
|
||||
if (!c_ptr)
|
||||
return 0;
|
||||
n_ptr = cluster_select_node(c_ptr, ref);
|
||||
if (n_ptr)
|
||||
return n_ptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref)
|
||||
{
|
||||
struct cluster *c_ptr;
|
||||
u32 c_num;
|
||||
u32 router;
|
||||
|
||||
if (!z_ptr)
|
||||
return 0;
|
||||
c_ptr = z_ptr->clusters[tipc_cluster(addr)];
|
||||
router = c_ptr ? cluster_select_router(c_ptr, ref) : 0;
|
||||
if (router)
|
||||
return router;
|
||||
|
||||
/* Links to any other clusters within the zone? */
|
||||
for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
|
||||
c_ptr = z_ptr->clusters[c_num];
|
||||
router = c_ptr ? cluster_select_router(c_ptr, ref) : 0;
|
||||
if (router)
|
||||
return router;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u32 zone_next_node(u32 addr)
|
||||
{
|
||||
struct cluster *c_ptr = cluster_find(addr);
|
||||
|
||||
if (c_ptr)
|
||||
return cluster_next_node(c_ptr, addr);
|
||||
return 0;
|
||||
}
|
||||
|
68
net/tipc/zone.h
Normal file
68
net/tipc/zone.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* net/tipc/zone.h: Include file for TIPC zone management routines
|
||||
*
|
||||
* Copyright (c) 2003-2005, Ericsson Research Canada
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Ericsson AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_ZONE_H
|
||||
#define _TIPC_ZONE_H
|
||||
|
||||
#include "node_subscr.h"
|
||||
#include "net.h"
|
||||
|
||||
|
||||
/**
|
||||
* struct _zone - TIPC zone structure
|
||||
* @addr: network address of zone
|
||||
* @clusters: array of pointers to all clusters within zone
|
||||
* @links: (used for inter-zone communication)
|
||||
*/
|
||||
|
||||
struct _zone {
|
||||
u32 addr;
|
||||
struct cluster *clusters[2]; /* currently limited to just 1 cluster */
|
||||
u32 links;
|
||||
};
|
||||
|
||||
struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
|
||||
u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref);
|
||||
void zone_remove_as_router(struct _zone *z_ptr, u32 router);
|
||||
void zone_send_external_routes(struct _zone *z_ptr, u32 dest);
|
||||
struct _zone *zone_create(u32 addr);
|
||||
void zone_delete(struct _zone *z_ptr);
|
||||
void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr);
|
||||
u32 zone_next_node(u32 addr);
|
||||
|
||||
static inline struct _zone *zone_find(u32 addr)
|
||||
{
|
||||
return net.zones[tipc_zone(addr)];
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue