diff options
Diffstat (limited to 'include/net')
52 files changed, 1861 insertions, 268 deletions
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index a7fb548..156c26b 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -86,6 +86,10 @@ do { \ /** * enum p9_msg_t - 9P message types + * @P9_TSTATFS: file system status request + * @P9_RSTATFS: file system status response + * @P9_TRENAME: rename request + * @P9_RRENAME: rename response * @P9_TVERSION: version handshake request * @P9_RVERSION: version handshake response * @P9_TAUTH: request to establish authentication channel @@ -125,6 +129,10 @@ do { \ */ enum p9_msg_t { + P9_TSTATFS = 8, + P9_RSTATFS, + P9_TRENAME = 20, + P9_RRENAME, P9_TVERSION = 100, P9_RVERSION, P9_TAUTH = 102, @@ -350,6 +358,31 @@ struct p9_wstat { }; /* Structures for Protocol Operations */ +struct p9_tstatfs { + u32 fid; +}; + +struct p9_rstatfs { + u32 type; + u32 bsize; + u64 blocks; + u64 bfree; + u64 bavail; + u64 files; + u64 ffree; + u64 fsid; + u32 namelen; +}; + +struct p9_trename { + u32 fid; + u32 newdirfid; + struct p9_str name; +}; + +struct p9_rrename { +}; + struct p9_tversion { u32 msize; struct p9_str version; diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 4f3760a..7dd3ed8 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -195,6 +195,8 @@ struct p9_fid { struct list_head dlist; /* list of all fids attached to a dentry */ }; +int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb); +int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name); int p9_client_version(struct p9_client *); struct p9_client *p9_client_create(const char *dev_name, char *options); void p9_client_destroy(struct p9_client *clnt); diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 1614d78..20725e2 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -30,7 +30,7 @@ struct unix_skb_parms { #endif }; -#define UNIXCB(skb) (*(struct unix_skb_parms*)&((skb)->cb)) +#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb)) #define UNIXCREDS(skb) (&UNIXCB((skb)).creds) #define UNIXSID(skb) (&UNIXCB((skb)).secid) @@ -45,21 +45,23 @@ struct unix_skb_parms { struct unix_sock { /* WARNING: sk has to be the first member */ struct sock sk; - struct unix_address *addr; - struct dentry *dentry; - struct vfsmount *mnt; + struct unix_address *addr; + struct dentry *dentry; + struct vfsmount *mnt; struct mutex readlock; - struct sock *peer; - struct sock *other; + struct sock *peer; + struct sock *other; struct list_head link; - atomic_long_t inflight; - spinlock_t lock; + atomic_long_t inflight; + spinlock_t lock; unsigned int gc_candidate : 1; unsigned int gc_maybe_cycle : 1; - wait_queue_head_t peer_wait; + struct socket_wq peer_wq; }; #define unix_sk(__sk) ((struct unix_sock *)__sk) +#define peer_wait peer_wq.wait + #ifdef CONFIG_SYSCTL extern int unix_sysctl_register(struct net *net); extern void unix_sysctl_unregister(struct net *net); diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ce3c99e..e42f6ed 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -107,6 +107,8 @@ struct hci_dev { unsigned long acl_last_tx; unsigned long sco_last_tx; + struct workqueue_struct *workqueue; + struct tasklet_struct cmd_task; struct tasklet_struct rx_task; struct tasklet_struct tx_task; @@ -636,8 +638,8 @@ int hci_register_notifier(struct notifier_block *nb); int hci_unregister_notifier(struct notifier_block *nb); int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); -int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); -int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); +void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); +void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 17a689f..7c695bf 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -30,11 +30,12 @@ #define L2CAP_DEFAULT_MIN_MTU 48 #define L2CAP_DEFAULT_FLUSH_TO 0xffff #define L2CAP_DEFAULT_TX_WINDOW 63 -#define L2CAP_DEFAULT_NUM_TO_ACK (L2CAP_DEFAULT_TX_WINDOW/5) #define L2CAP_DEFAULT_MAX_TX 3 #define L2CAP_DEFAULT_RETRANS_TO 1000 /* 1 second */ #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ #define L2CAP_DEFAULT_MAX_PDU_SIZE 672 +#define L2CAP_DEFAULT_ACK_TO 200 +#define L2CAP_LOCAL_BUSY_TRIES 12 #define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ #define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ @@ -55,6 +56,8 @@ struct l2cap_options { __u16 flush_to; __u8 mode; __u8 fcs; + __u8 max_tx; + __u16 txwin_size; }; #define L2CAP_CONNINFO 0x02 @@ -292,6 +295,7 @@ struct l2cap_conn { #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) #define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) +#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue) #define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) struct srej_list { @@ -320,7 +324,7 @@ struct l2cap_pinfo { __u8 conf_req[64]; __u8 conf_len; __u8 conf_state; - __u8 conn_state; + __u16 conn_state; __u8 next_tx_seq; __u8 expected_ack_seq; @@ -328,27 +332,35 @@ struct l2cap_pinfo { __u8 buffer_seq; __u8 buffer_seq_srej; __u8 srej_save_reqseq; + __u8 frames_sent; __u8 unacked_frames; __u8 retry_count; - __u8 num_to_ack; + __u8 num_acked; __u16 sdu_len; __u16 partial_sdu_len; struct sk_buff *sdu; __u8 ident; + __u8 tx_win; + __u8 max_tx; __u8 remote_tx_win; __u8 remote_max_tx; __u16 retrans_timeout; __u16 monitor_timeout; - __u16 max_pdu_size; + __u16 remote_mps; + __u16 mps; __le16 sport; + spinlock_t send_lock; struct timer_list retrans_timer; struct timer_list monitor_timer; + struct timer_list ack_timer; struct sk_buff_head tx_queue; struct sk_buff_head srej_queue; + struct sk_buff_head busy_queue; + struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; struct sock *next_c; @@ -367,19 +379,24 @@ struct l2cap_pinfo { #define L2CAP_CONF_MAX_CONF_REQ 2 #define L2CAP_CONF_MAX_CONF_RSP 2 -#define L2CAP_CONN_SAR_SDU 0x01 -#define L2CAP_CONN_SREJ_SENT 0x02 -#define L2CAP_CONN_WAIT_F 0x04 -#define L2CAP_CONN_SREJ_ACT 0x08 -#define L2CAP_CONN_SEND_PBIT 0x10 -#define L2CAP_CONN_REMOTE_BUSY 0x20 -#define L2CAP_CONN_LOCAL_BUSY 0x40 -#define L2CAP_CONN_REJ_ACT 0x80 +#define L2CAP_CONN_SAR_SDU 0x0001 +#define L2CAP_CONN_SREJ_SENT 0x0002 +#define L2CAP_CONN_WAIT_F 0x0004 +#define L2CAP_CONN_SREJ_ACT 0x0008 +#define L2CAP_CONN_SEND_PBIT 0x0010 +#define L2CAP_CONN_REMOTE_BUSY 0x0020 +#define L2CAP_CONN_LOCAL_BUSY 0x0040 +#define L2CAP_CONN_REJ_ACT 0x0080 +#define L2CAP_CONN_SEND_FBIT 0x0100 +#define L2CAP_CONN_RNR_SENT 0x0200 +#define L2CAP_CONN_SAR_RETRY 0x0400 #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); #define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); +#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ + jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); static inline int l2cap_tx_window_full(struct sock *sk) { diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h new file mode 100644 index 0000000..318ab94 --- /dev/null +++ b/include/net/caif/caif_dev.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/ sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CAIF_DEV_H_ +#define CAIF_DEV_H_ + +#include <net/caif/caif_layer.h> +#include <net/caif/cfcnfg.h> +#include <linux/caif/caif_socket.h> +#include <linux/if.h> + +/** + * struct caif_param - CAIF parameters. + * @size: Length of data + * @data: Binary Data Blob + */ +struct caif_param { + u16 size; + u8 data[256]; +}; + +/** + * struct caif_connect_request - Request data for CAIF channel setup. + * @protocol: Type of CAIF protocol to use (at, datagram etc) + * @sockaddr: Socket address to connect. + * @priority: Priority of the connection. + * @link_selector: Link selector (high bandwidth or low latency) + * @link_name: Name of the CAIF Link Layer to use. + * @param: Connect Request parameters (CAIF_SO_REQ_PARAM). + * + * This struct is used when connecting a CAIF channel. + * It contains all CAIF channel configuration options. + */ +struct caif_connect_request { + enum caif_protocol_type protocol; + struct sockaddr_caif sockaddr; + enum caif_channel_priority priority; + enum caif_link_selector link_selector; + char link_name[16]; + struct caif_param param; +}; + +/** + * caif_connect_client - Connect a client to CAIF Core Stack. + * @config: Channel setup parameters, specifying what address + * to connect on the Modem. + * @client_layer: User implementation of client layer. This layer + * MUST have receive and control callback functions + * implemented. + * + * This function connects a CAIF channel. The Client must implement + * the struct cflayer. This layer represents the Client layer and holds + * receive functions and control callback functions. Control callback + * function will receive information about connect/disconnect responses, + * flow control etc (see enum caif_control). + * E.g. CAIF Socket will call this function for each socket it connects + * and have one client_layer instance for each socket. + */ +int caif_connect_client(struct caif_connect_request *config, + struct cflayer *client_layer); + +/** + * caif_disconnect_client - Disconnects a client from the CAIF stack. + * + * @client_layer: Client layer to be removed. + */ +int caif_disconnect_client(struct cflayer *client_layer); + +/** + * caif_release_client - Release adaptation layer reference to client. + * + * @client_layer: Client layer. + * + * Releases a client/adaptation layer use of the caif stack. + * This function must be used after caif_disconnect_client to + * decrease the reference count of the service layer. + */ +void caif_release_client(struct cflayer *client_layer); + +/** + * connect_req_to_link_param - Translate configuration parameters + * from socket format to internal format. + * @cnfg: Pointer to configuration handler + * @con_req: Configuration parameters supplied in function + * caif_connect_client + * @channel_setup_param: Parameters supplied to the CAIF Core stack for + * setting up channels. + * + */ +int connect_req_to_link_param(struct cfcnfg *cnfg, + struct caif_connect_request *con_req, + struct cfctrl_link_param *channel_setup_param); + +/** + * get_caif_conf() - Get the configuration handler. + */ +struct cfcnfg *get_caif_conf(void); + + +#endif /* CAIF_DEV_H_ */ diff --git a/include/net/caif/caif_device.h b/include/net/caif/caif_device.h new file mode 100644 index 0000000..d02f044 --- /dev/null +++ b/include/net/caif/caif_device.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/ sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CAIF_DEVICE_H_ +#define CAIF_DEVICE_H_ +#include <linux/kernel.h> +#include <linux/net.h> +#include <linux/netdevice.h> +#include <linux/caif/caif_socket.h> +#include <net/caif/caif_device.h> + +/** + * struct caif_dev_common - data shared between CAIF drivers and stack. + * @flowctrl: Flow Control callback function. This function is + * supplied by CAIF Core Stack and is used by CAIF + * Link Layer to send flow-stop to CAIF Core. + * The flow information will be distributed to all + * clients of CAIF. + * + * @link_select: Profile of device, either high-bandwidth or + * low-latency. This member is set by CAIF Link + * Layer Device in order to indicate if this device + * is a high bandwidth or low latency device. + * + * @use_frag: CAIF Frames may be fragmented. + * Is set by CAIF Link Layer in order to indicate if the + * interface receives fragmented frames that must be + * assembled by CAIF Core Layer. + * + * @use_fcs: Indicate if Frame CheckSum (fcs) is used. + * Is set if the physical interface is + * using Frame Checksum on the CAIF Frames. + * + * @use_stx: Indicate STart of frame eXtension (stx) in use. + * Is set if the CAIF Link Layer expects + * CAIF Frames to start with the STX byte. + * + * This structure is shared between the CAIF drivers and the CAIF stack. + * It is used by the device to register its behavior. + * CAIF Core layer must set the member flowctrl in order to supply + * CAIF Link Layer with the flow control function. + * + */ + struct caif_dev_common { + void (*flowctrl)(struct net_device *net, int on); + enum caif_link_selector link_select; + int use_frag; + int use_fcs; + int use_stx; +}; + +#endif /* CAIF_DEVICE_H_ */ diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h new file mode 100644 index 0000000..25c472f --- /dev/null +++ b/include/net/caif/caif_layer.h @@ -0,0 +1,283 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland / sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CAIF_LAYER_H_ +#define CAIF_LAYER_H_ + +#include <linux/list.h> + +struct cflayer; +struct cfpkt; +struct cfpktq; +struct caif_payload_info; +struct caif_packet_funcs; + +#define CAIF_MAX_FRAMESIZE 4096 +#define CAIF_MAX_PAYLOAD_SIZE (4096 - 64) +#define CAIF_NEEDED_HEADROOM (10) +#define CAIF_NEEDED_TAILROOM (2) + +#define CAIF_LAYER_NAME_SZ 16 +#define CAIF_SUCCESS 1 +#define CAIF_FAILURE 0 + +/** + * caif_assert() - Assert function for CAIF. + * @assert: expression to evaluate. + * + * This function will print a error message and a do WARN_ON if the + * assertion failes. Normally this will do a stack up at the current location. + */ +#define caif_assert(assert) \ +do { \ + if (!(assert)) { \ + pr_err("caif:Assert detected:'%s'\n", #assert); \ + WARN_ON(!(assert)); \ + } \ +} while (0) + + +/** + * enum caif_ctrlcmd - CAIF Stack Control Signaling sent in layer.ctrlcmd(). + * + * @CAIF_CTRLCMD_FLOW_OFF_IND: Flow Control is OFF, transmit function + * should stop sending data + * + * @CAIF_CTRLCMD_FLOW_ON_IND: Flow Control is ON, transmit function + * can start sending data + * + * @CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: Remote end modem has decided to close + * down channel + * + * @CAIF_CTRLCMD_INIT_RSP: Called initially when the layer below + * has finished initialization + * + * @CAIF_CTRLCMD_DEINIT_RSP: Called when de-initialization is + * complete + * + * @CAIF_CTRLCMD_INIT_FAIL_RSP: Called if initialization fails + * + * @_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: CAIF Link layer temporarily cannot + * send more packets. + * @_CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: Called if CAIF Link layer is able + * to send packets again. + * @_CAIF_CTRLCMD_PHYIF_DOWN_IND: Called if CAIF Link layer is going + * down. + * + * These commands are sent upwards in the CAIF stack to the CAIF Client. + * They are used for signaling originating from the modem or CAIF Link Layer. + * These are either responses (*_RSP) or events (*_IND). + */ +enum caif_ctrlcmd { + CAIF_CTRLCMD_FLOW_OFF_IND, + CAIF_CTRLCMD_FLOW_ON_IND, + CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, + CAIF_CTRLCMD_INIT_RSP, + CAIF_CTRLCMD_DEINIT_RSP, + CAIF_CTRLCMD_INIT_FAIL_RSP, + _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, + _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND, + _CAIF_CTRLCMD_PHYIF_DOWN_IND, +}; + +/** + * enum caif_modemcmd - Modem Control Signaling, sent from CAIF Client + * to the CAIF Link Layer or modem. + * + * @CAIF_MODEMCMD_FLOW_ON_REQ: Flow Control is ON, transmit function + * can start sending data. + * + * @CAIF_MODEMCMD_FLOW_OFF_REQ: Flow Control is OFF, transmit function + * should stop sending data. + * + * @_CAIF_MODEMCMD_PHYIF_USEFULL: Notify physical layer that it is in use + * + * @_CAIF_MODEMCMD_PHYIF_USELESS: Notify physical layer that it is + * no longer in use. + * + * These are requests sent 'downwards' in the stack. + * Flow ON, OFF can be indicated to the modem. + */ +enum caif_modemcmd { + CAIF_MODEMCMD_FLOW_ON_REQ = 0, + CAIF_MODEMCMD_FLOW_OFF_REQ = 1, + _CAIF_MODEMCMD_PHYIF_USEFULL = 3, + _CAIF_MODEMCMD_PHYIF_USELESS = 4 +}; + +/** + * enum caif_direction - CAIF Packet Direction. + * Indicate if a packet is to be sent out or to be received in. + * @CAIF_DIR_IN: Incoming packet received. + * @CAIF_DIR_OUT: Outgoing packet to be transmitted. + */ +enum caif_direction { + CAIF_DIR_IN = 0, + CAIF_DIR_OUT = 1 +}; + +/** + * struct cflayer - CAIF Stack layer. + * Defines the framework for the CAIF Core Stack. + * @up: Pointer up to the layer above. + * @dn: Pointer down to the layer below. + * @node: List node used when layer participate in a list. + * @receive: Packet receive function. + * @transmit: Packet transmit funciton. + * @ctrlcmd: Used for control signalling upwards in the stack. + * @modemcmd: Used for control signaling downwards in the stack. + * @prio: Priority of this layer. + * @id: The identity of this layer + * @type: The type of this layer + * @name: Name of the layer. + * + * This structure defines the layered structure in CAIF. + * + * It defines CAIF layering structure, used by all CAIF Layers and the + * layers interfacing CAIF. + * + * In order to integrate with CAIF an adaptation layer on top of the CAIF stack + * and PHY layer below the CAIF stack + * must be implemented. These layer must follow the design principles below. + * + * Principles for layering of protocol layers: + * - All layers must use this structure. If embedding it, then place this + * structure first in the layer specific structure. + * + * - Each layer should not depend on any others layer private data. + * + * - In order to send data upwards do + * layer->up->receive(layer->up, packet); + * + * - In order to send data downwards do + * layer->dn->transmit(layer->dn, info, packet); + */ +struct cflayer { + struct cflayer *up; + struct cflayer *dn; + struct list_head node; + + /* + * receive() - Receive Function. + * Contract: Each layer must implement a receive function passing the + * CAIF packets upwards in the stack. + * Packet handling rules: + * - The CAIF packet (cfpkt) cannot be accessed after + * passing it to the next layer using up->receive(). + * - If parsing of the packet fails, the packet must be + * destroyed and -1 returned from the function. + * - If parsing succeeds (and above layers return OK) then + * the function must return a value > 0. + * + * Returns result < 0 indicates an error, 0 or positive value + * indicates success. + * + * @layr: Pointer to the current layer the receive function is + * implemented for (this pointer). + * @cfpkt: Pointer to CaifPacket to be handled. + */ + int (*receive)(struct cflayer *layr, struct cfpkt *cfpkt); + + /* + * transmit() - Transmit Function. + * Contract: Each layer must implement a transmit function passing the + * CAIF packet downwards in the stack. + * Packet handling rules: + * - The CAIF packet (cfpkt) ownership is passed to the + * transmit function. This means that the the packet + * cannot be accessed after passing it to the below + * layer using dn->transmit(). + * + * - If transmit fails, however, the ownership is returned + * to thecaller. The caller of "dn->transmit()" must + * destroy or resend packet. + * + * - Return value less than zero means error, zero or + * greater than zero means OK. + * + * result < 0 indicates an error, 0 or positive value + * indicate success. + * + * @layr: Pointer to the current layer the receive function + * isimplemented for (this pointer). + * @cfpkt: Pointer to CaifPacket to be handled. + */ + int (*transmit) (struct cflayer *layr, struct cfpkt *cfpkt); + + /* + * cttrlcmd() - Control Function upwards in CAIF Stack. + * Used for signaling responses (CAIF_CTRLCMD_*_RSP) + * and asynchronous events from the modem (CAIF_CTRLCMD_*_IND) + * + * @layr: Pointer to the current layer the receive function + * is implemented for (this pointer). + * @ctrl: Control Command. + */ + void (*ctrlcmd) (struct cflayer *layr, enum caif_ctrlcmd ctrl, + int phyid); + + /* + * modemctrl() - Control Function used for controlling the modem. + * Used to signal down-wards in the CAIF stack. + * Returns 0 on success, < 0 upon failure. + * + * @layr: Pointer to the current layer the receive function + * is implemented for (this pointer). + * @ctrl: Control Command. + */ + int (*modemcmd) (struct cflayer *layr, enum caif_modemcmd ctrl); + + unsigned short prio; + unsigned int id; + unsigned int type; + char name[CAIF_LAYER_NAME_SZ]; +}; + +/** + * layer_set_up() - Set the up pointer for a specified layer. + * @layr: Layer where up pointer shall be set. + * @above: Layer above. + */ +#define layer_set_up(layr, above) ((layr)->up = (struct cflayer *)(above)) + +/** + * layer_set_dn() - Set the down pointer for a specified layer. + * @layr: Layer where down pointer shall be set. + * @below: Layer below. + */ +#define layer_set_dn(layr, below) ((layr)->dn = (struct cflayer *)(below)) + +/** + * struct dev_info - Physical Device info information about physical layer. + * @dev: Pointer to native physical device. + * @id: Physical ID of the physical connection used by the + * logical CAIF connection. Used by service layers to + * identify their physical id to Caif MUX (CFMUXL)so + * that the MUX can add the correct physical ID to the + * packet. + */ +struct dev_info { + void *dev; + unsigned int id; +}; + +/** + * struct caif_payload_info - Payload information embedded in packet (sk_buff). + * + * @dev_info: Information about the receiving device. + * + * @hdr_len: Header length, used to align pay load on 32bit boundary. + * + * @channel_id: Channel ID of the logical CAIF connection. + * Used by mux to insert channel id into the caif packet. + */ +struct caif_payload_info { + struct dev_info *dev_info; + unsigned short hdr_len; + unsigned short channel_id; +}; + +#endif /* CAIF_LAYER_H_ */ diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h new file mode 100644 index 0000000..9fc2fc2 --- /dev/null +++ b/include/net/caif/cfcnfg.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CFCNFG_H_ +#define CFCNFG_H_ +#include <linux/spinlock.h> +#include <net/caif/caif_layer.h> +#include <net/caif/cfctrl.h> + +struct cfcnfg; + +/** + * enum cfcnfg_phy_type - Types of physical layers defined in CAIF Stack + * + * @CFPHYTYPE_FRAG: Fragmented frames physical interface. + * @CFPHYTYPE_CAIF: Generic CAIF physical interface + */ +enum cfcnfg_phy_type { + CFPHYTYPE_FRAG = 1, + CFPHYTYPE_CAIF, + CFPHYTYPE_MAX +}; + +/** + * enum cfcnfg_phy_preference - Physical preference HW Abstraction + * + * @CFPHYPREF_UNSPECIFIED: Default physical interface + * + * @CFPHYPREF_LOW_LAT: Default physical interface for low-latency + * traffic + * @CFPHYPREF_HIGH_BW: Default physical interface for high-bandwidth + * traffic + * @CFPHYPREF_LOOP: TEST only Loopback interface simulating modem + * responses. + * + */ +enum cfcnfg_phy_preference { + CFPHYPREF_UNSPECIFIED, + CFPHYPREF_LOW_LAT, + CFPHYPREF_HIGH_BW, + CFPHYPREF_LOOP +}; + +/** + * cfcnfg_create() - Create the CAIF configuration object. + */ +struct cfcnfg *cfcnfg_create(void); + +/** + * cfcnfg_remove() - Remove the CFCNFG object + * @cfg: config object + */ +void cfcnfg_remove(struct cfcnfg *cfg); + +/** + * cfcnfg_add_phy_layer() - Adds a physical layer to the CAIF stack. + * @cnfg: Pointer to a CAIF configuration object, created by + * cfcnfg_create(). + * @phy_type: Specifies the type of physical interface, e.g. + * CFPHYTYPE_FRAG. + * @dev: Pointer to link layer device + * @phy_layer: Specify the physical layer. The transmit function + * MUST be set in the structure. + * @phyid: The assigned physical ID for this layer, used in + * cfcnfg_add_adapt_layer to specify PHY for the link. + * @pref: The phy (link layer) preference. + * @fcs: Specify if checksum is used in CAIF Framing Layer. + * @stx: Specify if Start Of Frame eXtention is used. + */ + +void +cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, + void *dev, struct cflayer *phy_layer, u16 *phyid, + enum cfcnfg_phy_preference pref, + bool fcs, bool stx); + +/** + * cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack. + * + * @cnfg: Pointer to a CAIF configuration object, created by + * cfcnfg_create(). + * @phy_layer: Adaptation layer to be removed. + */ +int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer); + +/** + * cfcnfg_disconn_adapt_layer - Disconnects an adaptation layer. + * + * @cnfg: Pointer to a CAIF configuration object, created by + * cfcnfg_create(). + * @adap_layer: Adaptation layer to be removed. + */ +int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, + struct cflayer *adap_layer); + +/** + * cfcnfg_release_adap_layer - Used by client to release the adaptation layer. + * + * @adap_layer: Adaptation layer. + */ +void cfcnfg_release_adap_layer(struct cflayer *adap_layer); + +/** + * cfcnfg_add_adaptation_layer - Add an adaptation layer to the CAIF stack. + * + * The adaptation Layer is where the interface to application or higher-level + * driver functionality is implemented. + * + * @cnfg: Pointer to a CAIF configuration object, created by + * cfcnfg_create(). + * @param: Link setup parameters. + * @adap_layer: Specify the adaptation layer; the receive and + * flow-control functions MUST be set in the structure. + * + */ +int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, + struct cfctrl_link_param *param, + struct cflayer *adap_layer); + +/** + * cfcnfg_get_phyid() - Get physical ID, given type. + * Returns one of the physical interfaces matching the given type. + * Zero if no match is found. + * @cnfg: Configuration object + * @phy_pref: Caif Link Layer preference + */ +struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, + enum cfcnfg_phy_preference phy_pref); + +/** + * cfcnfg_get_named() - Get the Physical Identifier of CAIF Link Layer + * @cnfg: Configuration object + * @name: Name of the Physical Layer (Caif Link Layer) + */ +int cfcnfg_get_named(struct cfcnfg *cnfg, char *name); + +#endif /* CFCNFG_H_ */ diff --git a/include/net/caif/cfctrl.h b/include/net/caif/cfctrl.h new file mode 100644 index 0000000..997603f --- /dev/null +++ b/include/net/caif/cfctrl.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CFCTRL_H_ +#define CFCTRL_H_ +#include <net/caif/caif_layer.h> +#include <net/caif/cfsrvl.h> + +/* CAIF Control packet commands */ +enum cfctrl_cmd { + CFCTRL_CMD_LINK_SETUP = 0, + CFCTRL_CMD_LINK_DESTROY = 1, + CFCTRL_CMD_LINK_ERR = 2, + CFCTRL_CMD_ENUM = 3, + CFCTRL_CMD_SLEEP = 4, + CFCTRL_CMD_WAKE = 5, + CFCTRL_CMD_LINK_RECONF = 6, + CFCTRL_CMD_START_REASON = 7, + CFCTRL_CMD_RADIO_SET = 8, + CFCTRL_CMD_MODEM_SET = 9, + CFCTRL_CMD_MASK = 0xf +}; + +/* Channel types */ +enum cfctrl_srv { + CFCTRL_SRV_DECM = 0, + CFCTRL_SRV_VEI = 1, + CFCTRL_SRV_VIDEO = 2, + CFCTRL_SRV_DBG = 3, + CFCTRL_SRV_DATAGRAM = 4, + CFCTRL_SRV_RFM = 5, + CFCTRL_SRV_UTIL = 6, + CFCTRL_SRV_MASK = 0xf +}; + +#define CFCTRL_RSP_BIT 0x20 +#define CFCTRL_ERR_BIT 0x10 + +struct cfctrl_rsp { + void (*linksetup_rsp)(struct cflayer *layer, u8 linkid, + enum cfctrl_srv serv, u8 phyid, + struct cflayer *adapt_layer); + void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid); + void (*linkerror_ind)(void); + void (*enum_rsp)(void); + void (*sleep_rsp)(void); + void (*wake_rsp)(void); + void (*restart_rsp)(void); + void (*radioset_rsp)(void); + void (*reject_rsp)(struct cflayer *layer, u8 linkid, + struct cflayer *client_layer);; +}; + +/* Link Setup Parameters for CAIF-Links. */ +struct cfctrl_link_param { + enum cfctrl_srv linktype;/* (T3,T0) Type of Channel */ + u8 priority; /* (P4,P0) Priority of the channel */ + u8 phyid; /* (U2-U0) Physical interface to connect */ + u8 endpoint; /* (E1,E0) Endpoint for data channels */ + u8 chtype; /* (H1,H0) Channel-Type, applies to + * VEI, DEBUG */ + union { + struct { + u8 connid; /* (D7,D0) Video LinkId */ + } video; + + struct { + u32 connid; /* (N31,Ngit0) Connection ID used + * for Datagram */ + } datagram; + + struct { + u32 connid; /* Connection ID used for RFM */ + char volume[20]; /* Volume to mount for RFM */ + } rfm; /* Configuration for RFM */ + + struct { + u16 fifosize_kb; /* Psock FIFO size in KB */ + u16 fifosize_bufs; /* Psock # signal buffers */ + char name[16]; /* Name of the PSOCK service */ + u8 params[255]; /* Link setup Parameters> */ + u16 paramlen; /* Length of Link Setup + * Parameters */ + } utility; /* Configuration for Utility Links (Psock) */ + } u; +}; + +/* This structure is used internally in CFCTRL */ +struct cfctrl_request_info { + int sequence_no; + enum cfctrl_cmd cmd; + u8 channel_id; + struct cfctrl_link_param param; + struct cfctrl_request_info *next; + struct cflayer *client_layer; +}; + +struct cfctrl { + struct cfsrvl serv; + struct cfctrl_rsp res; + atomic_t req_seq_no; + atomic_t rsp_seq_no; + struct cfctrl_request_info *first_req; + /* Protects from simultaneous access to first_req list */ + spinlock_t info_list_lock; +#ifndef CAIF_NO_LOOP + u8 loop_linkid; + int loop_linkused[256]; + /* Protects simultaneous access to loop_linkid and loop_linkused */ + spinlock_t loop_linkid_lock; +#endif + +}; + +void cfctrl_enum_req(struct cflayer *cfctrl, u8 physlinkid); +int cfctrl_linkup_request(struct cflayer *cfctrl, + struct cfctrl_link_param *param, + struct cflayer *user_layer); +int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid, + struct cflayer *client); +void cfctrl_sleep_req(struct cflayer *cfctrl); +void cfctrl_wake_req(struct cflayer *cfctrl); +void cfctrl_getstartreason_req(struct cflayer *cfctrl); +struct cflayer *cfctrl_create(void); +void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn); +void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up); +struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer); +bool cfctrl_req_eq(struct cfctrl_request_info *r1, + struct cfctrl_request_info *r2); +void cfctrl_insert_req(struct cfctrl *ctrl, + struct cfctrl_request_info *req); +struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, + struct cfctrl_request_info *req); +void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer); + +#endif /* CFCTRL_H_ */ diff --git a/include/net/caif/cffrml.h b/include/net/caif/cffrml.h new file mode 100644 index 0000000..3f14d2e --- /dev/null +++ b/include/net/caif/cffrml.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CFFRML_H_ +#define CFFRML_H_ +#include <net/caif/caif_layer.h> + +struct cffrml; +struct cflayer *cffrml_create(u16 phyid, bool DoFCS); +void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up); +void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn); + +#endif /* CFFRML_H_ */ diff --git a/include/net/caif/cfmuxl.h b/include/net/caif/cfmuxl.h new file mode 100644 index 0000000..4e1b4f3 --- /dev/null +++ b/include/net/caif/cfmuxl.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CFMUXL_H_ +#define CFMUXL_H_ +#include <net/caif/caif_layer.h> + +struct cfsrvl; +struct cffrml; + +struct cflayer *cfmuxl_create(void); +int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid); +struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid); +int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *up, u8 phyid); +struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 linkid); +bool cfmuxl_is_phy_inuse(struct cflayer *layr, u8 phyid); +u8 cfmuxl_get_phyid(struct cflayer *layr, u8 channel_id); + +#endif /* CFMUXL_H_ */ diff --git a/include/net/caif/cfpkt.h b/include/net/caif/cfpkt.h new file mode 100644 index 0000000..fbc681b --- /dev/null +++ b/include/net/caif/cfpkt.h @@ -0,0 +1,274 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CFPKT_H_ +#define CFPKT_H_ +#include <net/caif/caif_layer.h> +#include <linux/types.h> +struct cfpkt; + +/* Create a CAIF packet. + * len: Length of packet to be created + * @return New packet. + */ +struct cfpkt *cfpkt_create(u16 len); + +/* Create a CAIF packet. + * data Data to copy. + * len Length of packet to be created + * @return New packet. + */ +struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len); +/* + * Destroy a CAIF Packet. + * pkt Packet to be destoyed. + */ +void cfpkt_destroy(struct cfpkt *pkt); + +/* + * Extract header from packet. + * + * pkt Packet to extract header data from. + * data Pointer to copy the header data into. + * len Length of head data to copy. + * @return zero on success and error code upon failure + */ +int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len); + +/* + * Peek header from packet. + * Reads data from packet without changing packet. + * + * pkt Packet to extract header data from. + * data Pointer to copy the header data into. + * len Length of head data to copy. + * @return zero on success and error code upon failure + */ +int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len); + +/* + * Extract header from trailer (end of packet). + * + * pkt Packet to extract header data from. + * data Pointer to copy the trailer data into. + * len Length of header data to copy. + * @return zero on success and error code upon failure + */ +int cfpkt_extr_trail(struct cfpkt *pkt, void *data, u16 len); + +/* + * Add header to packet. + * + * + * pkt Packet to add header data to. + * data Pointer to data to copy into the header. + * len Length of header data to copy. + * @return zero on success and error code upon failure + */ +int cfpkt_add_head(struct cfpkt *pkt, const void *data, u16 len); + +/* + * Add trailer to packet. + * + * + * pkt Packet to add trailer data to. + * data Pointer to data to copy into the trailer. + * len Length of trailer data to copy. + * @return zero on success and error code upon failure + */ +int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len); + +/* + * Pad trailer on packet. + * Moves data pointer in packet, no content copied. + * + * pkt Packet in which to pad trailer. + * len Length of padding to add. + * @return zero on success and error code upon failure + */ +int cfpkt_pad_trail(struct cfpkt *pkt, u16 len); + +/* + * Add a single byte to packet body (tail). + * + * pkt Packet in which to add byte. + * data Byte to add. + * @return zero on success and error code upon failure + */ +int cfpkt_addbdy(struct cfpkt *pkt, const u8 data); + +/* + * Add a data to packet body (tail). + * + * pkt Packet in which to add data. + * data Pointer to data to copy into the packet body. + * len Length of data to add. + * @return zero on success and error code upon failure + */ +int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len); + +/* + * Checks whether there are more data to process in packet. + * pkt Packet to check. + * @return true if more data are available in packet false otherwise + */ +bool cfpkt_more(struct cfpkt *pkt); + +/* + * Checks whether the packet is erroneous, + * i.e. if it has been attempted to extract more data than available in packet + * or writing more data than has been allocated in cfpkt_create(). + * pkt Packet to check. + * @return true on error false otherwise + */ +bool cfpkt_erroneous(struct cfpkt *pkt); + +/* + * Get the packet length. + * pkt Packet to get length from. + * @return Number of bytes in packet. + */ +u16 cfpkt_getlen(struct cfpkt *pkt); + +/* + * Set the packet length, by adjusting the trailer pointer according to length. + * pkt Packet to set length. + * len Packet length. + * @return Number of bytes in packet. + */ +int cfpkt_setlen(struct cfpkt *pkt, u16 len); + +/* + * cfpkt_append - Appends a packet's data to another packet. + * dstpkt: Packet to append data into, WILL BE FREED BY THIS FUNCTION + * addpkt: Packet to be appended and automatically released, + * WILL BE FREED BY THIS FUNCTION. + * expectlen: Packet's expected total length. This should be considered + * as a hint. + * NB: Input packets will be destroyed after appending and cannot be used + * after calling this function. + * @return The new appended packet. + */ +struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, struct cfpkt *addpkt, + u16 expectlen); + +/* + * cfpkt_split - Split a packet into two packets at the specified split point. + * pkt: Packet to be split (will contain the first part of the data on exit) + * pos: Position to split packet in two parts. + * @return The new packet, containing the second part of the data. + */ +struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos); + +/* + * Iteration function, iterates the packet buffers from start to end. + * + * Checksum iteration function used to iterate buffers + * (we may have packets consisting of a chain of buffers) + * pkt: Packet to calculate checksum for + * iter_func: Function pointer to iteration function + * chks: Checksum calculated so far. + * buf: Pointer to the buffer to checksum + * len: Length of buf. + * data: Initial checksum value. + * @return Checksum of buffer. + */ + +u16 cfpkt_iterate(struct cfpkt *pkt, + u16 (*iter_func)(u16 chks, void *buf, u16 len), + u16 data); + +/* Append by giving user access to packet buffer + * cfpkt Packet to append to + * buf Buffer inside pkt that user shall copy data into + * buflen Length of buffer and number of bytes added to packet + * @return 0 on error, 1 on success + */ +int cfpkt_raw_append(struct cfpkt *cfpkt, void **buf, unsigned int buflen); + +/* Extract by giving user access to packet buffer + * cfpkt Packet to extract from + * buf Buffer inside pkt that user shall copy data from + * buflen Length of buffer and number of bytes removed from packet + * @return 0 on error, 1 on success + */ +int cfpkt_raw_extract(struct cfpkt *cfpkt, void **buf, unsigned int buflen); + +/* Map from a "native" packet (e.g. Linux Socket Buffer) to a CAIF packet. + * dir - Direction indicating whether this packet is to be sent or received. + * nativepkt - The native packet to be transformed to a CAIF packet + * @return The mapped CAIF Packet CFPKT. + */ +struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt); + +/* Map from a CAIF packet to a "native" packet (e.g. Linux Socket Buffer). + * pkt - The CAIF packet to be transformed into a "native" packet. + * @return The native packet transformed from a CAIF packet. + */ +void *cfpkt_tonative(struct cfpkt *pkt); + +/* + * Insert a packet in the packet queue. + * pktq Packet queue to insert into + * pkt Packet to be inserted in queue + * prio Priority of packet + */ +void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, + unsigned short prio); + +/* + * Remove a packet from the packet queue. + * pktq Packet queue to fetch packets from. + * @return Dequeued packet. + */ +struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq); + +/* + * Peek into a packet from the packet queue. + * pktq Packet queue to fetch packets from. + * @return Peeked packet. + */ +struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq); + +/* + * Initiates the packet queue. + * @return Pointer to new packet queue. + */ +struct cfpktq *cfpktq_create(void); + +/* + * Get the number of packets in the queue. + * pktq Packet queue to fetch count from. + * @return Number of packets in queue. + */ +int cfpkt_qcount(struct cfpktq *pktq); + +/* + * Put content of packet into buffer for debuging purposes. + * pkt Packet to copy data from + * buf Buffer to copy data into + * buflen Length of data to copy + * @return Pointer to copied data + */ +char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen); + +/* + * Clones a packet and releases the original packet. + * This is used for taking ownership of a packet e.g queueing. + * pkt Packet to clone and release. + * @return Cloned packet. + */ +struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt); + + +/* + * Returns packet information for a packet. + * pkt Packet to get info from; + * @return Packet information + */ +struct caif_payload_info *cfpkt_info(struct cfpkt *pkt); +/*! @} */ +#endif /* CFPKT_H_ */ diff --git a/include/net/caif/cfserl.h b/include/net/caif/cfserl.h new file mode 100644 index 0000000..b837432 --- /dev/null +++ b/include/net/caif/cfserl.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CFSERL_H_ +#define CFSERL_H_ +#include <net/caif/caif_layer.h> + +struct cflayer *cfserl_create(int type, int instance, bool use_stx); +#endif /* CFSERL_H_ */ diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h new file mode 100644 index 0000000..2dc9eb1 --- /dev/null +++ b/include/net/caif/cfsrvl.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CFSRVL_H_ +#define CFSRVL_H_ +#include <linux/list.h> +#include <linux/stddef.h> +#include <linux/types.h> +#include <linux/kref.h> + +struct cfsrvl { + struct cflayer layer; + bool open; + bool phy_flow_on; + bool modem_flow_on; + struct dev_info dev_info; + struct kref ref; +}; + +void cfsrvl_release(struct kref *kref); +struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); +struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info); +struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info); +struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info); +struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info); +struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); +bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); +void cfservl_destroy(struct cflayer *layer); +void cfsrvl_init(struct cfsrvl *service, + u8 channel_id, + struct dev_info *dev_info); +bool cfsrvl_ready(struct cfsrvl *service, int *err); +u8 cfsrvl_getphyid(struct cflayer *layer); + +static inline void cfsrvl_get(struct cflayer *layr) +{ + struct cfsrvl *s; + if (layr == NULL) + return; + s = container_of(layr, struct cfsrvl, layer); + kref_get(&s->ref); +} + +static inline void cfsrvl_put(struct cflayer *layr) +{ + struct cfsrvl *s; + if (layr == NULL) + return; + s = container_of(layr, struct cfsrvl, layer); + kref_put(&s->ref, cfsrvl_release); +} + +#endif /* CFSRVL_H_ */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3d134a1..b44a2e5 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -511,6 +511,7 @@ struct mpath_info { * @basic_rates: basic rates in IEEE 802.11 format * (or NULL for no change) * @basic_rates_len: number of basic rates + * @ap_isolate: do not forward packets between connected stations */ struct bss_parameters { int use_cts_prot; @@ -518,6 +519,7 @@ struct bss_parameters { int use_short_slot_time; u8 *basic_rates; u8 basic_rates_len; + int ap_isolate; }; struct mesh_config { @@ -704,6 +706,10 @@ struct cfg80211_crypto_settings { * @key_len: length of WEP key for shared key authentication * @key_idx: index of WEP key for shared key authentication * @key: WEP key for shared key authentication + * @local_state_change: This is a request for a local state only, i.e., no + * Authentication frame is to be transmitted and authentication state is + * to be changed without having to wait for a response from the peer STA + * (AP). */ struct cfg80211_auth_request { struct cfg80211_bss *bss; @@ -712,6 +718,7 @@ struct cfg80211_auth_request { enum nl80211_auth_type auth_type; const u8 *key; u8 key_len, key_idx; + bool local_state_change; }; /** @@ -744,12 +751,15 @@ struct cfg80211_assoc_request { * @ie: Extra IEs to add to Deauthentication frame or %NULL * @ie_len: Length of ie buffer in octets * @reason_code: The reason code for the deauthentication + * @local_state_change: This is a request for a local state only, i.e., no + * Deauthentication frame is to be transmitted. */ struct cfg80211_deauth_request { struct cfg80211_bss *bss; const u8 *ie; size_t ie_len; u16 reason_code; + bool local_state_change; }; /** @@ -762,12 +772,15 @@ struct cfg80211_deauth_request { * @ie: Extra IEs to add to Disassociation frame or %NULL * @ie_len: Length of ie buffer in octets * @reason_code: The reason code for the disassociation + * @local_state_change: This is a request for a local state only, i.e., no + * Disassociation frame is to be transmitted. */ struct cfg80211_disassoc_request { struct cfg80211_bss *bss; const u8 *ie; size_t ie_len; u16 reason_code; + bool local_state_change; }; /** @@ -953,7 +966,11 @@ struct cfg80211_pmksa { * * @set_txq_params: Set TX queue parameters * - * @set_channel: Set channel + * @set_channel: Set channel for a given wireless interface. Some devices + * may support multi-channel operation (by channel hopping) so cfg80211 + * doesn't verify much. Note, however, that the passed netdev may be + * %NULL as well if the user requested changing the channel for the + * device itself, or for a monitor interface. * * @scan: Request to do a scan. If returning zero, the scan request is given * the driver, and will be valid until passed to cfg80211_scan_done(). @@ -1007,6 +1024,9 @@ struct cfg80211_pmksa { * RSN IE. It allows for faster roaming between WPA2 BSSIDs. * @del_pmksa: Delete a cached PMKID. * @flush_pmksa: Flush all cached PMKIDs. + * @set_power_mgmt: Configure WLAN power management. A timeout value of -1 + * allows the driver to adjust the dynamic ps timeout value. + * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. * */ struct cfg80211_ops { @@ -1079,7 +1099,7 @@ struct cfg80211_ops { int (*set_txq_params)(struct wiphy *wiphy, struct ieee80211_txq_params *params); - int (*set_channel)(struct wiphy *wiphy, + int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); @@ -1152,6 +1172,10 @@ struct cfg80211_ops { int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); + + int (*set_cqm_rssi_config)(struct wiphy *wiphy, + struct net_device *dev, + s32 rssi_thold, u32 rssi_hyst); }; /* @@ -1441,6 +1465,8 @@ struct cfg80211_cached_keys; * @list: (private) Used to collect the interfaces * @netdev: (private) Used to reference back to the netdev * @current_bss: (private) Used by the internal configuration code + * @channel: (private) Used by the internal configuration code to track + * user-set AP, monitor and WDS channels for wireless extensions * @bssid: (private) Used by the internal configuration code * @ssid: (private) Used by the internal configuration code * @ssid_len: (private) Used by the internal configuration code @@ -1487,6 +1513,7 @@ struct wireless_dev { struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES]; struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; struct cfg80211_internal_bss *current_bss; /* associated / joined */ + struct ieee80211_channel *channel; bool ps; int ps_timeout; @@ -1627,7 +1654,7 @@ struct ieee80211_radiotap_iterator { const struct ieee80211_radiotap_namespace *current_namespace; unsigned char *_arg, *_next_ns_data; - uint32_t *_next_bitmap; + __le32 *_next_bitmap; unsigned char *this_arg; int this_arg_index; @@ -2337,4 +2364,18 @@ bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, const u8 *buf, size_t len, bool ack, gfp_t gfp); + +/** + * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event + * @dev: network device + * @rssi_event: the triggered RSSI event + * @gfp: context flags + * + * This function is called when a configured connection quality monitoring + * rssi threshold reached event occurs. + */ +void cfg80211_cqm_rssi_notify(struct net_device *dev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp); + #endif /* __NET_CFG80211_H */ diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h index 52da6c3..bbcde32 100644 --- a/include/net/dn_fib.h +++ b/include/net/dn_fib.h @@ -50,10 +50,6 @@ struct dn_fib_info { __le16 fib_prefsrc; __u32 fib_priority; __u32 fib_metrics[RTAX_MAX]; -#define dn_fib_mtu fib_metrics[RTAX_MTU-1] -#define dn_fib_window fib_metrics[RTAX_WINDOW-1] -#define dn_fib_rtt fib_metrics[RTAX_RTT-1] -#define dn_fib_advmss fib_metrics[RTAX_ADVMSS-1] int fib_nhs; int fib_power; struct dn_fib_nh fib_nh[0]; diff --git a/include/net/dst.h b/include/net/dst.h index ce078cd..612069b 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -168,6 +168,12 @@ static inline void dst_use(struct dst_entry *dst, unsigned long time) dst->lastuse = time; } +static inline void dst_use_noref(struct dst_entry *dst, unsigned long time) +{ + dst->__use++; + dst->lastuse = time; +} + static inline struct dst_entry * dst_clone(struct dst_entry * dst) { @@ -177,11 +183,67 @@ struct dst_entry * dst_clone(struct dst_entry * dst) } extern void dst_release(struct dst_entry *dst); + +static inline void refdst_drop(unsigned long refdst) +{ + if (!(refdst & SKB_DST_NOREF)) + dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK)); +} + +/** + * skb_dst_drop - drops skb dst + * @skb: buffer + * + * Drops dst reference count if a reference was taken. + */ static inline void skb_dst_drop(struct sk_buff *skb) { - if (skb->_skb_dst) - dst_release(skb_dst(skb)); - skb->_skb_dst = 0UL; + if (skb->_skb_refdst) { + refdst_drop(skb->_skb_refdst); + skb->_skb_refdst = 0UL; + } +} + +static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb) +{ + nskb->_skb_refdst = oskb->_skb_refdst; + if (!(nskb->_skb_refdst & SKB_DST_NOREF)) + dst_clone(skb_dst(nskb)); +} + +/** + * skb_dst_force - makes sure skb dst is refcounted + * @skb: buffer + * + * If dst is not yet refcounted, let's do it + */ +static inline void skb_dst_force(struct sk_buff *skb) +{ + if (skb_dst_is_noref(skb)) { + WARN_ON(!rcu_read_lock_held()); + skb->_skb_refdst &= ~SKB_DST_NOREF; + dst_clone(skb_dst(skb)); + } +} + + +/** + * skb_tunnel_rx - prepare skb for rx reinsert + * @skb: buffer + * @dev: tunnel device + * + * After decapsulation, packet is going to re-enter (netif_rx()) our stack, + * so make some cleanups, and perform accounting. + */ +static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) +{ + skb->dev = dev; + /* TODO : stats should be SMP safe */ + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + skb->rxhash = 0; + skb_dst_drop(skb); + nf_reset(skb); } /* Children define the path of the packet through the @@ -225,21 +287,6 @@ static inline void dst_confirm(struct dst_entry *dst) neigh_confirm(dst->neighbour); } -static inline void dst_negative_advice(struct dst_entry **dst_p, - struct sock *sk) -{ - struct dst_entry * dst = *dst_p; - if (dst && dst->ops->negative_advice) { - *dst_p = dst->ops->negative_advice(dst); - - if (dst != *dst_p) { - extern void sk_reset_txq(struct sock *sk); - - sk_reset_txq(sk); - } - } -} - static inline void dst_link_failure(struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index c49086d..e8923bc 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -104,7 +104,7 @@ static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla) return frh->table; } -extern struct fib_rules_ops *fib_rules_register(struct fib_rules_ops *, struct net *); +extern struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *, struct net *); extern void fib_rules_unregister(struct fib_rules_ops *); extern void fib_rules_cleanup_ops(struct fib_rules_ops *); @@ -114,4 +114,5 @@ extern int fib_rules_lookup(struct fib_rules_ops *, extern int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table, u32 flags); +extern u32 fib_default_rule_pref(struct fib_rules_ops *ops); #endif diff --git a/include/net/flow.h b/include/net/flow.h index 809970b..bb08692 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -86,11 +86,26 @@ struct flowi { struct net; struct sock; -typedef int (*flow_resolve_t)(struct net *net, struct flowi *key, u16 family, - u8 dir, void **objp, atomic_t **obj_refp); +struct flow_cache_ops; + +struct flow_cache_object { + const struct flow_cache_ops *ops; +}; + +struct flow_cache_ops { + struct flow_cache_object *(*get)(struct flow_cache_object *); + int (*check)(struct flow_cache_object *); + void (*delete)(struct flow_cache_object *); +}; + +typedef struct flow_cache_object *(*flow_resolve_t)( + struct net *net, struct flowi *key, u16 family, + u8 dir, struct flow_cache_object *oldobj, void *ctx); + +extern struct flow_cache_object *flow_cache_lookup( + struct net *net, struct flowi *key, u16 family, + u8 dir, flow_resolve_t resolver, void *ctx); -extern void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, - u8 dir, flow_resolve_t resolver); extern void flow_cache_flush(void); extern atomic_t flow_cache_genid; diff --git a/include/net/icmp.h b/include/net/icmp.h index 15b3dfe..6e991e0 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -48,15 +48,4 @@ extern void icmp_out_count(struct net *net, unsigned char type); /* Move into dst.h ? */ extern int xrlim_allow(struct dst_entry *dst, int timeout); -struct raw_sock { - /* inet_sock has to be the first member */ - struct inet_sock inet; - struct icmp_filter filter; -}; - -static inline struct raw_sock *raw_sk(const struct sock *sk) -{ - return (struct raw_sock *)sk; -} - #endif /* _ICMP_H */ diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 545d8b0..f95ff8d 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -32,6 +32,13 @@ #ifdef __KERNEL__ +enum { + INET6_IFADDR_STATE_DAD, + INET6_IFADDR_STATE_POSTDAD, + INET6_IFADDR_STATE_UP, + INET6_IFADDR_STATE_DEAD, +}; + struct inet6_ifaddr { struct in6_addr addr; __u32 prefix_len; @@ -40,6 +47,9 @@ struct inet6_ifaddr { __u32 prefered_lft; atomic_t refcnt; spinlock_t lock; + spinlock_t state_lock; + + int state; __u8 probes; __u8 flags; @@ -54,16 +64,15 @@ struct inet6_ifaddr { struct inet6_dev *idev; struct rt6_info *rt; - struct inet6_ifaddr *lst_next; /* next addr in addr_lst */ - struct inet6_ifaddr *if_next; /* next addr in inet6_dev */ + struct hlist_node addr_lst; + struct list_head if_list; #ifdef CONFIG_IPV6_PRIVACY - struct inet6_ifaddr *tmp_next; /* next addr in tempaddr_lst */ + struct list_head tmp_list; struct inet6_ifaddr *ifpub; int regen_count; #endif - - int dead; + struct rcu_head rcu; }; struct ip6_sf_socklist { @@ -151,9 +160,9 @@ struct ipv6_devstat { }; struct inet6_dev { - struct net_device *dev; + struct net_device *dev; - struct inet6_ifaddr *addr_list; + struct list_head addr_list; struct ifmcaddr6 *mc_list; struct ifmcaddr6 *mc_tomb; @@ -175,7 +184,7 @@ struct inet6_dev { #ifdef CONFIG_IPV6_PRIVACY u8 rndid[8]; struct timer_list regen_timer; - struct inet6_ifaddr *tempaddr_list; + struct list_head tempaddr_list; #endif struct neigh_parms *nd_parms; diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index f13ddc2..aae08f6 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -38,5 +38,5 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk, extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); -extern int inet6_csk_xmit(struct sk_buff *skb, int ipfragok); +extern int inet6_csk_xmit(struct sk_buff *skb); #endif /* _INET6_CONNECTION_SOCK_H */ diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 696d6e4..b6d3b55 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -36,9 +36,8 @@ struct tcp_congestion_ops; * (i.e. things that depend on the address family) */ struct inet_connection_sock_af_ops { - int (*queue_xmit)(struct sk_buff *skb, int ipfragok); - void (*send_check)(struct sock *sk, int len, - struct sk_buff *skb); + int (*queue_xmit)(struct sk_buff *skb); + void (*send_check)(struct sock *sk, struct sk_buff *skb); int (*rebuild_header)(struct sock *sk); int (*conn_request)(struct sock *sk, struct sk_buff *skb); struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb, diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 83fd344..1653de5 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -21,6 +21,7 @@ #include <linux/string.h> #include <linux/types.h> #include <linux/jhash.h> +#include <linux/netdevice.h> #include <net/flow.h> #include <net/sock.h> diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 79f67ea..a066fdd 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -224,7 +224,9 @@ static inline struct net *twsk_net(const struct inet_timewait_sock *twsk) { #ifdef CONFIG_NET_NS - return rcu_dereference(twsk->tw_net); + return rcu_dereference_raw(twsk->tw_net); /* protected by locking, */ + /* reference counting, */ + /* initialization, or RCU. */ #else return &init_net; #endif diff --git a/include/net/ip.h b/include/net/ip.h index 503994a..63548f0 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -101,7 +101,7 @@ extern int ip_do_nat(struct sk_buff *skb); extern void ip_send_check(struct iphdr *ip); extern int __ip_local_out(struct sk_buff *skb); extern int ip_local_out(struct sk_buff *skb); -extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); +extern int ip_queue_xmit(struct sk_buff *skb); extern void ip_init(void); extern int ip_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, @@ -184,6 +184,12 @@ extern struct local_ports { } sysctl_local_ports; extern void inet_get_local_port_range(int *low, int *high); +extern unsigned long *sysctl_local_reserved_ports; +static inline int inet_is_reserved_local_port(int port) +{ + return test_bit(port, sysctl_local_reserved_ports); +} + extern int sysctl_ip_default_ttl; extern int sysctl_ip_nonlocal_bind; @@ -393,6 +399,7 @@ extern int ip_options_rcv_srr(struct sk_buff *skb); * Functions provided by ip_sockglue.c */ +extern int ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); extern int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc); diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 86f46c4..4b1dc11 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -88,34 +88,37 @@ struct rt6_info { struct dst_entry dst; } u; - struct inet6_dev *rt6i_idev; - #define rt6i_dev u.dst.dev #define rt6i_nexthop u.dst.neighbour #define rt6i_expires u.dst.expires + /* + * Tail elements of dst_entry (__refcnt etc.) + * and these elements (rarely used in hot path) are in + * the same cache line. + */ + struct fib6_table *rt6i_table; struct fib6_node *rt6i_node; struct in6_addr rt6i_gateway; - - u32 rt6i_flags; - u32 rt6i_metric; - atomic_t rt6i_ref; - /* more non-fragment space at head required */ - unsigned short rt6i_nfheader_len; - - u8 rt6i_protocol; + atomic_t rt6i_ref; - struct fib6_table *rt6i_table; + /* These are in a separate cache line. */ + struct rt6key rt6i_dst ____cacheline_aligned_in_smp; + u32 rt6i_flags; + struct rt6key rt6i_src; + u32 rt6i_metric; - struct rt6key rt6i_dst; + struct inet6_dev *rt6i_idev; #ifdef CONFIG_XFRM u32 rt6i_flow_cache_genid; #endif + /* more non-fragment space at head required */ + unsigned short rt6i_nfheader_len; - struct rt6key rt6i_src; + u8 rt6i_protocol; }; static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 68f6783..278312c 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -152,9 +152,9 @@ static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst, static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, struct in6_addr *daddr, struct in6_addr *saddr) { - write_lock(&sk->sk_dst_lock); + spin_lock(&sk->sk_dst_lock); __ip6_dst_store(sk, dst, daddr, saddr); - write_unlock(&sk->sk_dst_lock); + spin_unlock(&sk->sk_dst_lock); } static inline int ipv6_unicast_destination(struct sk_buff *skb) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e72fb10..eba5cc0 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -422,7 +422,7 @@ static inline int __ipv6_addr_diff(const void *token1, const void *token2, int a for (i = 0; i < addrlen; i++) { __be32 xb = a1[i] ^ a2[i]; if (xb) - return i * 32 + 32 - fls(ntohl(xb)); + return i * 32 + 31 - __fls(ntohl(xb)); } /* @@ -482,8 +482,7 @@ extern int ip6_rcv_finish(struct sk_buff *skb); extern int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, - struct ipv6_txoptions *opt, - int ipfragok); + struct ipv6_txoptions *opt); extern int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, @@ -504,7 +503,8 @@ extern int ip6_append_data(struct sock *sk, struct ipv6_txoptions *opt, struct flowi *fl, struct rt6_info *rt, - unsigned int flags); + unsigned int flags, + int dontfrag); extern int ip6_push_pending_frames(struct sock *sk); @@ -578,9 +578,11 @@ extern int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len); extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); +extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len); extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, u32 info, u8 *payload); extern void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info); +extern void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu); extern int inet6_release(struct socket *sock); extern int inet6_bind(struct socket *sock, struct sockaddr *uaddr, diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index b2b98f3..3afdb21 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -323,7 +323,7 @@ typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, struct iw_handler_def { /* Array of handlers for standard ioctls - * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT] + * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST] */ const iw_handler * standard; /* Number of handlers defined (more precisely, index of the diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 45d7d44..e24b036 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -144,6 +144,8 @@ struct ieee80211_low_level_stats { * new beacon (beaconing modes) * @BSS_CHANGED_BEACON_ENABLED: Beaconing should be * enabled/disabled (beaconing modes) + * @BSS_CHANGED_CQM: Connection quality monitor config changed + * @BSS_CHANGED_IBSS: IBSS join status changed */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -156,6 +158,10 @@ enum ieee80211_bss_change { BSS_CHANGED_BSSID = 1<<7, BSS_CHANGED_BEACON = 1<<8, BSS_CHANGED_BEACON_ENABLED = 1<<9, + BSS_CHANGED_CQM = 1<<10, + BSS_CHANGED_IBSS = 1<<11, + + /* when adding here, make sure to change ieee80211_reconfig */ }; /** @@ -165,6 +171,8 @@ enum ieee80211_bss_change { * to that BSS) that can change during the lifetime of the BSS. * * @assoc: association status + * @ibss_joined: indicates whether this station is part of an IBSS + * or not * @aid: association ID number, valid only when @assoc is true * @use_cts_prot: use CTS protection * @use_short_preamble: use 802.11b short preamble; @@ -183,13 +191,19 @@ enum ieee80211_bss_change { * the current band. * @bssid: The BSSID for this BSS * @enable_beacon: whether beaconing should be enabled or not + * @channel_type: Channel type for this BSS -- the hardware might be + * configured for HT40+ while this BSS only uses no-HT, for + * example. * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info). * This field is only valid when the channel type is one of the HT types. + * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value + * implies disabled + * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis */ struct ieee80211_bss_conf { const u8 *bssid; /* association related data */ - bool assoc; + bool assoc, ibss_joined; u16 aid; /* erp related data */ bool use_cts_prot; @@ -202,6 +216,9 @@ struct ieee80211_bss_conf { u64 timestamp; u32 basic_rates; u16 ht_operation_mode; + s32 cqm_rssi_thold; + u32 cqm_rssi_hyst; + enum nl80211_channel_type channel_type; }; /** @@ -267,6 +284,9 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 * MLME command (internal to mac80211 to figure out whether to send TX * status to user space) + * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame + * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this + * frame and selects the maximum number of streams that it can use. */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -290,6 +310,9 @@ enum mac80211_tx_control_flags { IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20), IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), + IEEE80211_TX_CTL_LDPC = BIT(22), + IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), +#define IEEE80211_TX_CTL_STBC_SHIFT 23 }; /** @@ -388,11 +411,11 @@ struct ieee80211_tx_rate { * @status: union for status data * @driver_data: array of driver_data pointers * @ampdu_ack_len: number of acked aggregated frames. - * relevant only if IEEE80211_TX_STATUS_AMPDU was set. + * relevant only if IEEE80211_TX_STAT_AMPDU was set. * @ampdu_ack_map: block ack bit map for the aggregation. - * relevant only if IEEE80211_TX_STATUS_AMPDU was set. + * relevant only if IEEE80211_TX_STAT_AMPDU was set. * @ampdu_len: number of aggregated frames. - * relevant only if IEEE80211_TX_STATUS_AMPDU was set. + * relevant only if IEEE80211_TX_STAT_AMPDU was set. * @ack_signal: signal strength of the ACK frame */ struct ieee80211_tx_info { @@ -543,7 +566,6 @@ enum mac80211_rx_flags { * @signal: signal strength when receiving this frame, either in dBm, in dB or * unspecified depending on the hardware capabilities flags * @IEEE80211_HW_SIGNAL_* - * @noise: noise when receiving this frame, in dBm. * @antenna: antenna used * @rate_idx: index of data rate into band's supported rates or MCS index if * HT rates are use (RX_FLAG_HT) @@ -554,7 +576,6 @@ struct ieee80211_rx_status { enum ieee80211_band band; int freq; int signal; - int noise; int antenna; int rate_idx; int flag; @@ -580,11 +601,15 @@ struct ieee80211_rx_status { * may turn the device off as much as possible. Typically, this flag will * be set when an interface is set UP but not associated or scanning, but * it can also be unset in that case when monitor interfaces are active. + * @IEEE80211_CONF_QOS: Enable 802.11e QoS also know as WMM (Wireless + * Multimedia). On some drivers (iwlwifi is one of know) we have + * to enable/disable QoS explicitly. */ enum ieee80211_conf_flags { IEEE80211_CONF_MONITOR = (1<<0), IEEE80211_CONF_PS = (1<<1), IEEE80211_CONF_IDLE = (1<<2), + IEEE80211_CONF_QOS = (1<<3), }; @@ -599,6 +624,7 @@ enum ieee80211_conf_flags { * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed + * @IEEE80211_CONF_CHANGE_QOS: Quality of service was enabled or disabled */ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_SMPS = BIT(1), @@ -609,6 +635,7 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), IEEE80211_CONF_CHANGE_IDLE = BIT(8), + IEEE80211_CONF_CHANGE_QOS = BIT(9), }; /** @@ -649,6 +676,9 @@ enum ieee80211_smps_mode { * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the * powersave documentation below. This variable is valid only when * the CONF_PS flag is set. + * @dynamic_ps_forced_timeout: The dynamic powersave timeout (in ms) configured + * by cfg80211 (essentially, wext) If set, this value overrules the value + * chosen by mac80211 based on ps qos network latency. * * @power_level: requested transmit power (in dBm) * @@ -668,7 +698,7 @@ enum ieee80211_smps_mode { */ struct ieee80211_conf { u32 flags; - int power_level, dynamic_ps_timeout; + int power_level, dynamic_ps_timeout, dynamic_ps_forced_timeout; int max_sleep_period; u16 listen_interval; @@ -682,6 +712,28 @@ struct ieee80211_conf { }; /** + * struct ieee80211_channel_switch - holds the channel switch data + * + * The information provided in this structure is required for channel switch + * operation. + * + * @timestamp: value in microseconds of the 64-bit Time Synchronization + * Function (TSF) timer when the frame containing the channel switch + * announcement was received. This is simply the rx.mactime parameter + * the driver passed into mac80211. + * @block_tx: Indicates whether transmission must be blocked before the + * scheduled channel switch, as indicated by the AP. + * @channel: the new channel to switch to + * @count: the number of TBTT's until the channel switch event + */ +struct ieee80211_channel_switch { + u64 timestamp; + bool block_tx; + struct ieee80211_channel *channel; + u8 count; +}; + +/** * struct ieee80211_vif - per-interface data * * Data in this structure is continually present for driver @@ -907,10 +959,6 @@ enum ieee80211_tkip_key_type { * one milliwatt. This is the preferred method since it is standardized * between different devices. @max_signal does not need to be set. * - * @IEEE80211_HW_NOISE_DBM: - * Hardware can provide noise (radio interference) values in units dBm, - * decibel difference from one milliwatt. - * * @IEEE80211_HW_SPECTRUM_MGMT: * Hardware supports spectrum management defined in 802.11h * Measurement, Channel Switch, Quieting, TPC @@ -954,6 +1002,17 @@ enum ieee80211_tkip_key_type { * Hardware can provide ack status reports of Tx frames to * the stack. * + * @IEEE80211_HW_CONNECTION_MONITOR: + * The hardware performs its own connection monitoring, including + * periodic keep-alives to the AP and probing the AP on beacon loss. + * When this flag is set, signaling beacon-loss will cause an immediate + * change to disassociated state. + * + * @IEEE80211_HW_SUPPORTS_CQM_RSSI: + * Hardware can do connection quality monitoring - i.e. it can monitor + * connection quality related parameters, such as the RSSI level and + * provide notifications if configured trigger levels are reached. + * */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -963,7 +1022,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, IEEE80211_HW_SIGNAL_DBM = 1<<6, - IEEE80211_HW_NOISE_DBM = 1<<7, + /* use this hole */ IEEE80211_HW_SPECTRUM_MGMT = 1<<8, IEEE80211_HW_AMPDU_AGGREGATION = 1<<9, IEEE80211_HW_SUPPORTS_PS = 1<<10, @@ -975,6 +1034,8 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, + IEEE80211_HW_CONNECTION_MONITOR = 1<<19, + IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, }; /** @@ -1591,6 +1652,11 @@ enum ieee80211_ampdu_mlme_action { * @flush: Flush all pending frames from the hardware queue, making sure * that the hardware queues are empty. If the parameter @drop is set * to %true, pending frames may be dropped. The callback can sleep. + * + * @channel_switch: Drivers that need (or want) to offload the channel + * switch operation for CSAs received from the AP may implement this + * callback. They must then call ieee80211_chswitch_done() to indicate + * completion of the channel switch. */ struct ieee80211_ops { int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1606,7 +1672,7 @@ struct ieee80211_ops { struct ieee80211_bss_conf *info, u32 changed); u64 (*prepare_multicast)(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mc_list); + struct netdev_hw_addr_list *mc_list); void (*configure_filter)(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, @@ -1621,7 +1687,7 @@ struct ieee80211_ops { struct ieee80211_key_conf *conf, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); - int (*hw_scan)(struct ieee80211_hw *hw, + int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_scan_request *req); void (*sw_scan_start)(struct ieee80211_hw *hw); void (*sw_scan_complete)(struct ieee80211_hw *hw); @@ -1646,13 +1712,16 @@ struct ieee80211_ops { struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn); - + int (*get_survey)(struct ieee80211_hw *hw, int idx, + struct survey_info *survey); void (*rfkill_poll)(struct ieee80211_hw *hw); void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class); #ifdef CONFIG_NL80211_TESTMODE int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len); #endif void (*flush)(struct ieee80211_hw *hw, bool drop); + void (*channel_switch)(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch); }; /** @@ -1802,7 +1871,10 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw); * ieee80211_rx - receive frame * * Use this function to hand received frames to mac80211. The receive - * buffer in @skb must start with an IEEE 802.11 header. + * buffer in @skb must start with an IEEE 802.11 header. In case of a + * paged @skb is used, the driver is recommended to put the ieee80211 + * header of the frame on the linear part of the @skb to avoid memory + * allocation and/or memcpy by the stack. * * This function may not be called in IRQ context. Calls to this function * for a single hardware must be synchronized against each other. Calls to @@ -2364,12 +2436,52 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, * * @vif: &struct ieee80211_vif pointer from the add_interface callback. * - * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and - * IEEE80211_CONF_PS is set, the driver needs to inform whenever the + * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING and + * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the * hardware is not receiving beacons with this function. */ void ieee80211_beacon_loss(struct ieee80211_vif *vif); +/** + * ieee80211_connection_loss - inform hardware has lost connection to the AP + * + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * + * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING, and + * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver + * needs to inform if the connection to the AP has been lost. + * + * This function will cause immediate change to disassociated state, + * without connection recovery attempts. + */ +void ieee80211_connection_loss(struct ieee80211_vif *vif); + +/** + * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring + * rssi threshold triggered + * + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @rssi_event: the RSSI trigger event type + * @gfp: context flags + * + * When the %IEEE80211_HW_SUPPORTS_CQM_RSSI is set, and a connection quality + * monitoring is configured with an rssi threshold, the driver will inform + * whenever the rssi level reaches the threshold. + */ +void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp); + +/** + * ieee80211_chswitch_done - Complete channel switch process + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @success: make the channel switch successful or not + * + * Complete the channel switch post-process: set the new operational channel + * and wake up the suspended queues. + */ +void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); + /* Rate control API */ /** diff --git a/include/net/mld.h b/include/net/mld.h new file mode 100644 index 0000000..467143c --- /dev/null +++ b/include/net/mld.h @@ -0,0 +1,75 @@ +#ifndef LINUX_MLD_H +#define LINUX_MLD_H + +#include <linux/in6.h> +#include <linux/icmpv6.h> + +/* MLDv1 Query/Report/Done */ +struct mld_msg { + struct icmp6hdr mld_hdr; + struct in6_addr mld_mca; +}; + +#define mld_type mld_hdr.icmp6_type +#define mld_code mld_hdr.icmp6_code +#define mld_cksum mld_hdr.icmp6_cksum +#define mld_maxdelay mld_hdr.icmp6_maxdelay +#define mld_reserved mld_hdr.icmp6_dataun.un_data16[1] + +/* Multicast Listener Discovery version 2 headers */ +/* MLDv2 Report */ +struct mld2_grec { + __u8 grec_type; + __u8 grec_auxwords; + __be16 grec_nsrcs; + struct in6_addr grec_mca; + struct in6_addr grec_src[0]; +}; + +struct mld2_report { + struct icmp6hdr mld2r_hdr; + struct mld2_grec mld2r_grec[0]; +}; + +#define mld2r_type mld2r_hdr.icmp6_type +#define mld2r_resv1 mld2r_hdr.icmp6_code +#define mld2r_cksum mld2r_hdr.icmp6_cksum +#define mld2r_resv2 mld2r_hdr.icmp6_dataun.un_data16[0] +#define mld2r_ngrec mld2r_hdr.icmp6_dataun.un_data16[1] + +/* MLDv2 Query */ +struct mld2_query { + struct icmp6hdr mld2q_hdr; + struct in6_addr mld2q_mca; +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 mld2q_qrv:3, + mld2q_suppress:1, + mld2q_resv2:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 mld2q_resv2:4, + mld2q_suppress:1, + mld2q_qrv:3; +#else +#error "Please fix <asm/byteorder.h>" +#endif + __u8 mld2q_qqic; + __be16 mld2q_nsrcs; + struct in6_addr mld2q_srcs[0]; +}; + +#define mld2q_type mld2q_hdr.icmp6_type +#define mld2q_code mld2q_hdr.icmp6_code +#define mld2q_cksum mld2q_hdr.icmp6_cksum +#define mld2q_mrc mld2q_hdr.icmp6_maxdelay +#define mld2q_resv1 mld2q_hdr.icmp6_dataun.un_data16[1] + +/* Max Response Code */ +#define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) +#define MLDV2_EXP(thresh, nbmant, nbexp, value) \ + ((value) < (thresh) ? (value) : \ + ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ + (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) + +#define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) + +#endif diff --git a/include/net/neighbour.h b/include/net/neighbour.h index da1d58b..eb21340 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -299,6 +299,20 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) return 0; } +#ifdef CONFIG_BRIDGE_NETFILTER +static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) +{ + unsigned seq, hh_alen; + + do { + seq = read_seqbegin(&hh->hh_lock); + hh_alen = HH_DATA_ALIGN(ETH_HLEN); + memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN); + } while (read_seqretry(&hh->hh_lock, seq)); + return 0; +} +#endif + static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) { unsigned seq; diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h index ff4982a..81a31c0 100644 --- a/include/net/netns/generic.h +++ b/include/net/netns/generic.h @@ -14,11 +14,8 @@ * The rules are simple: * 1. set pernet_operations->id. After register_pernet_device you * will have the id of your private pointer. - * 2. Either set pernet_operations->size (to have the code allocate and - * free a private structure pointed to from struct net ) or - * call net_assign_generic() to put the private data on the struct - * net (most preferably this should be done in the ->init callback - * of the ops registered); + * 2. set pernet_operations->size to have the code allocate and free + * a private structure pointed to from struct net. * 3. do not change this pointer while the net is alive; * 4. do not try to have any private reference on the net_generic object. * @@ -46,6 +43,4 @@ static inline void *net_generic(struct net *net, int id) return ptr; } - -extern int net_assign_generic(struct net *net, int id, void *data); #endif diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 2764994..d68c3f1 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -55,19 +55,14 @@ struct netns_ipv4 { int sysctl_rt_cache_rebuild_count; int current_rt_cache_rebuild_count; - struct timer_list rt_secret_timer; atomic_t rt_genid; #ifdef CONFIG_IP_MROUTE - struct sock *mroute_sk; - struct mfc_cache **mfc_cache_array; - struct vif_device *vif_table; - int maxvif; - atomic_t cache_resolve_queue_len; - int mroute_do_assert; - int mroute_do_pim; -#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) - int mroute_reg_vif_num; +#ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES + struct mr_table *mrt; +#else + struct list_head mr_tables; + struct fib_rules_ops *mr_rules_ops; #endif #endif }; diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 1f11ebc..81abfcb 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h @@ -59,15 +59,11 @@ struct netns_ipv6 { struct sock *tcp_sk; struct sock *igmp_sk; #ifdef CONFIG_IPV6_MROUTE - struct sock *mroute6_sk; - struct mfc6_cache **mfc6_cache_array; - struct mif_device *vif6_table; - int maxvif; - atomic_t cache_resolve_queue_len; - int mroute_do_assert; - int mroute_do_pim; -#ifdef CONFIG_IPV6_PIMSM_V2 - int mroute_reg_vif_num; +#ifndef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES + struct mr6_table *mrt6; +#else + struct list_head mr6_tables; + struct fib_rules_ops *mr6_rules_ops; #endif #endif }; diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index b6cdc33..9d4d87c 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -12,7 +12,7 @@ struct qdisc_walker { int (*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *); }; -#define QDISC_ALIGNTO 32 +#define QDISC_ALIGNTO 64 #define QDISC_ALIGN(len) (((len) + QDISC_ALIGNTO-1) & ~(QDISC_ALIGNTO-1)) static inline void *qdisc_priv(struct Qdisc *q) diff --git a/include/net/raw.h b/include/net/raw.h index 6c14a65..43c5750 100644 --- a/include/net/raw.h +++ b/include/net/raw.h @@ -19,6 +19,7 @@ #include <net/protocol.h> +#include <linux/icmp.h> extern struct proto raw_prot; @@ -56,4 +57,16 @@ int raw_seq_open(struct inode *ino, struct file *file, void raw_hash_sk(struct sock *sk); void raw_unhash_sk(struct sock *sk); +struct raw_sock { + /* inet_sock has to be the first member */ + struct inet_sock inet; + struct icmp_filter filter; + u32 ipmr_table; +}; + +static inline struct raw_sock *raw_sk(const struct sock *sk) +{ + return (struct raw_sock *)sk; +} + #endif /* _RAW_H */ diff --git a/include/net/route.h b/include/net/route.h index 2c9fba7..af6cf4b 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -112,7 +112,22 @@ extern void rt_cache_flush_batch(void); extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); -extern int ip_route_input(struct sk_buff*, __be32 dst, __be32 src, u8 tos, struct net_device *devin); + +extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, + u8 tos, struct net_device *devin, bool noref); + +static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, + u8 tos, struct net_device *devin) +{ + return ip_route_input_common(skb, dst, src, tos, devin, false); +} + +static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, + u8 tos, struct net_device *devin) +{ + return ip_route_input_common(skb, dst, src, tos, devin, true); +} + extern unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, unsigned short new_mtu, struct net_device *dev); extern void ip_rt_send_redirect(struct sk_buff *skb); diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 67dc08e..03ca5d8 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -73,6 +73,7 @@ struct Qdisc { struct sk_buff_head q; struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; + struct rcu_head rcu_head; }; struct Qdisc_class_ops { diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index fa6cde5..65946bc 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -269,7 +269,7 @@ enum { #define SCTP_MIB_MAX __SCTP_MIB_MAX struct sctp_mib { unsigned long mibs[SCTP_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; /* Print debugging messages. */ @@ -547,7 +547,7 @@ for (pos = chunk->subh.fwdtsn_hdr->skip;\ #define WORD_ROUND(s) (((s)+3)&~3) /* Make a new instance of type. */ -#define t_new(type, flags) (type *)kmalloc(sizeof(type), flags) +#define t_new(type, flags) (type *)kzalloc(sizeof(type), flags) /* Compare two timevals. */ #define tv_lt(s, t) \ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 61d73e3..4088c89 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -438,7 +438,7 @@ sctp_vtag_verify_either(const struct sctp_chunk *chunk, */ if ((!sctp_test_T_bit(chunk) && (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)) || - (sctp_test_T_bit(chunk) && + (sctp_test_T_bit(chunk) && asoc->c.peer_vtag && (ntohl(chunk->sctp_hdr->vtag) == asoc->c.peer_vtag))) { return 1; } diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 219043a..6173c61 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -643,17 +643,15 @@ struct sctp_pf { struct sctp_datamsg { /* Chunks waiting to be submitted to lower layer. */ struct list_head chunks; - /* Chunks that have been transmitted. */ - size_t msg_size; /* Reference counting. */ atomic_t refcnt; /* When is this message no longer interesting to the peer? */ unsigned long expires_at; /* Did the messenge fail to send? */ int send_error; - char send_failed; - /* Control whether chunks from this message can be abandoned. */ - char can_abandon; + u8 send_failed:1, + can_abandon:1, /* can chunks from this message can be abandoned. */ + can_delay; /* should this message be Nagle delayed */ }; struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *, @@ -757,7 +755,6 @@ struct sctp_chunk { #define SCTP_NEED_FRTX 0x1 #define SCTP_DONT_FRTX 0x2 __u16 rtt_in_progress:1, /* This chunk used for RTT calc? */ - resent:1, /* Has this chunk ever been resent. */ has_tsn:1, /* Does this chunk have a TSN yet? */ has_ssn:1, /* Does this chunk have a SSN yet? */ singleton:1, /* Only chunk in the packet? */ @@ -879,7 +876,30 @@ struct sctp_transport { /* Reference counting. */ atomic_t refcnt; - int dead; + int dead:1, + /* RTO-Pending : A flag used to track if one of the DATA + * chunks sent to this address is currently being + * used to compute a RTT. If this flag is 0, + * the next DATA chunk sent to this destination + * should be used to compute a RTT and this flag + * should be set. Every time the RTT + * calculation completes (i.e. the DATA chunk + * is SACK'd) clear this flag. + */ + rto_pending:1, + + /* + * hb_sent : a flag that signals that we have a pending + * heartbeat. + */ + hb_sent:1, + + /* Is the Path MTU update pending on this tranport */ + pmtu_pending:1, + + /* Is this structure kfree()able? */ + malloced:1; + /* This is the peer's IP address and port. */ union sctp_addr ipaddr; @@ -909,22 +929,6 @@ struct sctp_transport { /* SRTT : The current smoothed round trip time. */ __u32 srtt; - /* RTO-Pending : A flag used to track if one of the DATA - * chunks sent to this address is currently being - * used to compute a RTT. If this flag is 0, - * the next DATA chunk sent to this destination - * should be used to compute a RTT and this flag - * should be set. Every time the RTT - * calculation completes (i.e. the DATA chunk - * is SACK'd) clear this flag. - * hb_sent : a flag that signals that we have a pending heartbeat. - */ - __u8 rto_pending; - __u8 hb_sent; - - /* Flag to track the current fast recovery state */ - __u8 fast_recovery; - /* * These are the congestion stats. */ @@ -944,9 +948,6 @@ struct sctp_transport { __u32 burst_limited; /* Holds old cwnd when max.burst is applied */ - /* TSN marking the fast recovery exit point */ - __u32 fast_recovery_exit; - /* Destination */ struct dst_entry *dst; /* Source address. */ @@ -977,9 +978,6 @@ struct sctp_transport { */ __u16 pathmaxrxt; - /* is the Path MTU update pending on this tranport */ - __u8 pmtu_pending; - /* PMTU : The current known path MTU. */ __u32 pathmtu; @@ -1026,8 +1024,6 @@ struct sctp_transport { /* This is the list of transports that have chunks to send. */ struct list_head send_ready; - int malloced; /* Is this structure kfree()able? */ - /* State information saved for SFR_CACC algorithm. The key * idea in SFR_CACC is to maintain state at the sender on a * per-destination basis when a changeover happens. @@ -1069,7 +1065,7 @@ void sctp_transport_route(struct sctp_transport *, union sctp_addr *, struct sctp_sock *); void sctp_transport_pmtu(struct sctp_transport *); void sctp_transport_free(struct sctp_transport *); -void sctp_transport_reset_timers(struct sctp_transport *, int); +void sctp_transport_reset_timers(struct sctp_transport *); void sctp_transport_hold(struct sctp_transport *); void sctp_transport_put(struct sctp_transport *); void sctp_transport_update_rto(struct sctp_transport *, __u32); @@ -1723,6 +1719,12 @@ struct sctp_association { /* Highest TSN that is acknowledged by incoming SACKs. */ __u32 highest_sacked; + /* TSN marking the fast recovery exit point */ + __u32 fast_recovery_exit; + + /* Flag to track the current fast recovery state */ + __u8 fast_recovery; + /* The number of unacknowledged data chunks. Reported through * the SCTP_STATUS sockopt. */ diff --git a/include/net/snmp.h b/include/net/snmp.h index 692ee00..92456f1 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -52,26 +52,11 @@ struct snmp_mib { * count on the 20Gb/s + networks people expect in a few years time! */ -/* - * The rule for padding: - * Best is power of two because then the right structure can be found by a - * simple shift. The structure should be always cache line aligned. - * gcc needs n=alignto(cachelinesize, popcnt(sizeof(bla_mib))) shift/add - * instructions to emulate multiply in case it is not power-of-two. - * Currently n is always <=3 for all sizes so simple cache line alignment - * is enough. - * - * The best solution would be a global CPU local area , especially on 64 - * and 128byte cacheline machine it makes a *lot* of sense -AK - */ - -#define __SNMP_MIB_ALIGN__ ____cacheline_aligned - /* IPstats */ #define IPSTATS_MIB_MAX __IPSTATS_MIB_MAX struct ipstats_mib { unsigned long mibs[IPSTATS_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; /* ICMP */ #define ICMP_MIB_DUMMY __ICMP_MIB_MAX @@ -79,36 +64,36 @@ struct ipstats_mib { struct icmp_mib { unsigned long mibs[ICMP_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; #define ICMPMSG_MIB_MAX __ICMPMSG_MIB_MAX struct icmpmsg_mib { unsigned long mibs[ICMPMSG_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; /* ICMP6 (IPv6-ICMP) */ #define ICMP6_MIB_MAX __ICMP6_MIB_MAX struct icmpv6_mib { unsigned long mibs[ICMP6_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; #define ICMP6MSG_MIB_MAX __ICMP6MSG_MIB_MAX struct icmpv6msg_mib { unsigned long mibs[ICMP6MSG_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; /* TCP */ #define TCP_MIB_MAX __TCP_MIB_MAX struct tcp_mib { unsigned long mibs[TCP_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; /* UDP */ #define UDP_MIB_MAX __UDP_MIB_MAX struct udp_mib { unsigned long mibs[UDP_MIB_MAX]; -} __SNMP_MIB_ALIGN__; +}; /* Linux */ #define LINUX_MIB_MAX __LINUX_MIB_MAX @@ -148,6 +133,8 @@ struct linux_xfrm_mib { __this_cpu_add(mib[0]->mibs[field], addend) #define SNMP_ADD_STATS_USER(mib, field, addend) \ this_cpu_add(mib[1]->mibs[field], addend) +#define SNMP_ADD_STATS(mib, field, addend) \ + this_cpu_add(mib[0]->mibs[field], addend) /* * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr" * to make @ptr a non-percpu pointer. diff --git a/include/net/sock.h b/include/net/sock.h index 1ad6435..5697caf 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -159,7 +159,7 @@ struct sock_common { * @sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings * @sk_lock: synchronizer * @sk_rcvbuf: size of receive buffer in bytes - * @sk_sleep: sock wait queue + * @sk_wq: sock wait queue and async head * @sk_dst_cache: destination cache * @sk_dst_lock: destination cache lock * @sk_policy: flow policy @@ -177,6 +177,7 @@ struct sock_common { * %SO_OOBINLINE settings, %SO_TIMESTAMPING settings * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) + * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) * @sk_gso_max_size: Maximum GSO segment size to build * @sk_lingertime: %SO_LINGER l_linger setting @@ -198,6 +199,7 @@ struct sock_common { * @sk_rcvlowat: %SO_RCVLOWAT setting * @sk_rcvtimeo: %SO_RCVTIMEO setting * @sk_sndtimeo: %SO_SNDTIMEO setting + * @sk_rxhash: flow hash received from netif layer * @sk_filter: socket filtering instructions * @sk_protinfo: private area, net family specific, when not using slab * @sk_timer: sock cleanup timer @@ -255,14 +257,13 @@ struct sock { struct sk_buff *head; struct sk_buff *tail; int len; - int limit; } sk_backlog; - wait_queue_head_t *sk_sleep; + struct socket_wq *sk_wq; struct dst_entry *sk_dst_cache; #ifdef CONFIG_XFRM struct xfrm_policy *sk_policy[2]; #endif - rwlock_t sk_dst_lock; + spinlock_t sk_dst_lock; atomic_t sk_rmem_alloc; atomic_t sk_wmem_alloc; atomic_t sk_omem_alloc; @@ -276,9 +277,13 @@ struct sock { int sk_forward_alloc; gfp_t sk_allocation; int sk_route_caps; + int sk_route_nocaps; int sk_gso_type; unsigned int sk_gso_max_size; int sk_rcvlowat; +#ifdef CONFIG_RPS + __u32 sk_rxhash; +#endif unsigned long sk_flags; unsigned long sk_lingertime; struct sk_buff_head sk_error_queue; @@ -595,19 +600,32 @@ static inline int sk_stream_memory_free(struct sock *sk) /* OOB backlog add */ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) { - if (!sk->sk_backlog.tail) { - sk->sk_backlog.head = sk->sk_backlog.tail = skb; - } else { + /* dont let skb dst not refcounted, we are going to leave rcu lock */ + skb_dst_force(skb); + + if (!sk->sk_backlog.tail) + sk->sk_backlog.head = skb; + else sk->sk_backlog.tail->next = skb; - sk->sk_backlog.tail = skb; - } + + sk->sk_backlog.tail = skb; skb->next = NULL; } +/* + * Take into account size of receive queue and backlog queue + */ +static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb) +{ + unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc); + + return qsize + skb->truesize > sk->sk_rcvbuf; +} + /* The per-socket spinlock must be held here. */ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb) { - if (sk->sk_backlog.len >= max(sk->sk_backlog.limit, sk->sk_rcvbuf << 1)) + if (sk_rcvqueues_full(sk, skb)) return -ENOBUFS; __sk_add_backlog(sk, skb); @@ -620,6 +638,40 @@ static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) return sk->sk_backlog_rcv(sk, skb); } +static inline void sock_rps_record_flow(const struct sock *sk) +{ +#ifdef CONFIG_RPS + struct rps_sock_flow_table *sock_flow_table; + + rcu_read_lock(); + sock_flow_table = rcu_dereference(rps_sock_flow_table); + rps_record_sock_flow(sock_flow_table, sk->sk_rxhash); + rcu_read_unlock(); +#endif +} + +static inline void sock_rps_reset_flow(const struct sock *sk) +{ +#ifdef CONFIG_RPS + struct rps_sock_flow_table *sock_flow_table; + + rcu_read_lock(); + sock_flow_table = rcu_dereference(rps_sock_flow_table); + rps_reset_sock_flow(sock_flow_table, sk->sk_rxhash); + rcu_read_unlock(); +#endif +} + +static inline void sock_rps_save_rxhash(struct sock *sk, u32 rxhash) +{ +#ifdef CONFIG_RPS + if (unlikely(sk->sk_rxhash != rxhash)) { + sock_rps_reset_flow(sk); + sk->sk_rxhash = rxhash; + } +#endif +} + #define sk_wait_event(__sk, __timeo, __condition) \ ({ int __rc; \ release_sock(__sk); \ @@ -974,6 +1026,16 @@ extern void release_sock(struct sock *sk); SINGLE_DEPTH_NESTING) #define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock)) +static inline void lock_sock_bh(struct sock *sk) +{ + spin_lock_bh(&sk->sk_lock.slock); +} + +static inline void unlock_sock_bh(struct sock *sk) +{ + spin_unlock_bh(&sk->sk_lock.slock); +} + extern struct sock *sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot); @@ -1160,6 +1222,10 @@ static inline void sk_set_socket(struct sock *sk, struct socket *sock) sk->sk_socket = sock; } +static inline wait_queue_head_t *sk_sleep(struct sock *sk) +{ + return &sk->sk_wq->wait; +} /* Detach socket from process context. * Announce socket dead, detach it from wait queue and inode. * Note that parent inode held reference count on this struct sock, @@ -1172,14 +1238,14 @@ static inline void sock_orphan(struct sock *sk) write_lock_bh(&sk->sk_callback_lock); sock_set_flag(sk, SOCK_DEAD); sk_set_socket(sk, NULL); - sk->sk_sleep = NULL; + sk->sk_wq = NULL; write_unlock_bh(&sk->sk_callback_lock); } static inline void sock_graft(struct sock *sk, struct socket *parent) { write_lock_bh(&sk->sk_callback_lock); - sk->sk_sleep = &parent->wait; + rcu_assign_pointer(sk->sk_wq, parent->wq); parent->sk = sk; sk_set_socket(sk, parent); security_sock_graft(sk, parent); @@ -1192,7 +1258,9 @@ extern unsigned long sock_i_ino(struct sock *sk); static inline struct dst_entry * __sk_dst_get(struct sock *sk) { - return sk->sk_dst_cache; + return rcu_dereference_check(sk->sk_dst_cache, rcu_read_lock_held() || + sock_owned_by_user(sk) || + lockdep_is_held(&sk->sk_lock.slock)); } static inline struct dst_entry * @@ -1200,50 +1268,65 @@ sk_dst_get(struct sock *sk) { struct dst_entry *dst; - read_lock(&sk->sk_dst_lock); - dst = sk->sk_dst_cache; + rcu_read_lock(); + dst = rcu_dereference(sk->sk_dst_cache); if (dst) dst_hold(dst); - read_unlock(&sk->sk_dst_lock); + rcu_read_unlock(); return dst; } +extern void sk_reset_txq(struct sock *sk); + +static inline void dst_negative_advice(struct sock *sk) +{ + struct dst_entry *ndst, *dst = __sk_dst_get(sk); + + if (dst && dst->ops->negative_advice) { + ndst = dst->ops->negative_advice(dst); + + if (ndst != dst) { + rcu_assign_pointer(sk->sk_dst_cache, ndst); + sk_reset_txq(sk); + } + } +} + static inline void __sk_dst_set(struct sock *sk, struct dst_entry *dst) { struct dst_entry *old_dst; sk_tx_queue_clear(sk); - old_dst = sk->sk_dst_cache; - sk->sk_dst_cache = dst; + /* + * This can be called while sk is owned by the caller only, + * with no state that can be checked in a rcu_dereference_check() cond + */ + old_dst = rcu_dereference_raw(sk->sk_dst_cache); + rcu_assign_pointer(sk->sk_dst_cache, dst); dst_release(old_dst); } static inline void sk_dst_set(struct sock *sk, struct dst_entry *dst) { - write_lock(&sk->sk_dst_lock); + spin_lock(&sk->sk_dst_lock); __sk_dst_set(sk, dst); - write_unlock(&sk->sk_dst_lock); + spin_unlock(&sk->sk_dst_lock); } static inline void __sk_dst_reset(struct sock *sk) { - struct dst_entry *old_dst; - - sk_tx_queue_clear(sk); - old_dst = sk->sk_dst_cache; - sk->sk_dst_cache = NULL; - dst_release(old_dst); + __sk_dst_set(sk, NULL); } static inline void sk_dst_reset(struct sock *sk) { - write_lock(&sk->sk_dst_lock); + spin_lock(&sk->sk_dst_lock); __sk_dst_reset(sk); - write_unlock(&sk->sk_dst_lock); + spin_unlock(&sk->sk_dst_lock); } extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); @@ -1257,6 +1340,12 @@ static inline int sk_can_gso(const struct sock *sk) extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst); +static inline void sk_nocaps_add(struct sock *sk, int flags) +{ + sk->sk_route_nocaps |= flags; + sk->sk_route_caps &= ~flags; +} + static inline int skb_copy_to_page(struct sock *sk, char __user *from, struct sk_buff *skb, struct page *page, int off, int copy) @@ -1314,12 +1403,12 @@ static inline int sk_has_allocations(const struct sock *sk) } /** - * sk_has_sleeper - check if there are any waiting processes - * @sk: socket + * wq_has_sleeper - check if there are any waiting processes + * @sk: struct socket_wq * - * Returns true if socket has waiting processes + * Returns true if socket_wq has waiting processes * - * The purpose of the sk_has_sleeper and sock_poll_wait is to wrap the memory + * The purpose of the wq_has_sleeper and sock_poll_wait is to wrap the memory * barrier call. They were added due to the race found within the tcp code. * * Consider following tcp code paths: @@ -1332,9 +1421,10 @@ static inline int sk_has_allocations(const struct sock *sk) * ... ... * tp->rcv_nxt check sock_def_readable * ... { - * schedule ... - * if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - * wake_up_interruptible(sk->sk_sleep) + * schedule rcu_read_lock(); + * wq = rcu_dereference(sk->sk_wq); + * if (wq && waitqueue_active(&wq->wait)) + * wake_up_interruptible(&wq->wait) * ... * } * @@ -1343,19 +1433,18 @@ static inline int sk_has_allocations(const struct sock *sk) * could then endup calling schedule and sleep forever if there are no more * data on the socket. * - * The sk_has_sleeper is always called right after a call to read_lock, so we - * can use smp_mb__after_lock barrier. */ -static inline int sk_has_sleeper(struct sock *sk) +static inline bool wq_has_sleeper(struct socket_wq *wq) { + /* * We need to be sure we are in sync with the * add_wait_queue modifications to the wait queue. * * This memory barrier is paired in the sock_poll_wait. */ - smp_mb__after_lock(); - return sk->sk_sleep && waitqueue_active(sk->sk_sleep); + smp_mb(); + return wq && waitqueue_active(&wq->wait); } /** @@ -1364,7 +1453,7 @@ static inline int sk_has_sleeper(struct sock *sk) * @wait_address: socket wait queue * @p: poll_table * - * See the comments in the sk_has_sleeper function. + * See the comments in the wq_has_sleeper function. */ static inline void sock_poll_wait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) @@ -1375,7 +1464,7 @@ static inline void sock_poll_wait(struct file *filp, * We need to be sure we are in sync with the * socket flags modification. * - * This memory barrier is paired in the sk_has_sleeper. + * This memory barrier is paired in the wq_has_sleeper. */ smp_mb(); } @@ -1557,7 +1646,24 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) sk->sk_stamp = kt; } -extern void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb); +extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, + struct sk_buff *skb); + +static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, + struct sk_buff *skb) +{ +#define FLAGS_TS_OR_DROPS ((1UL << SOCK_RXQ_OVFL) | \ + (1UL << SOCK_RCVTSTAMP) | \ + (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \ + (1UL << SOCK_TIMESTAMPING_SOFTWARE) | \ + (1UL << SOCK_TIMESTAMPING_RAW_HARDWARE) | \ + (1UL << SOCK_TIMESTAMPING_SYS_HARDWARE)) + + if (sk->sk_flags & FLAGS_TS_OR_DROPS) + __sock_recv_ts_and_drops(msg, sk, skb); + else + sk->sk_stamp = skb->tstamp; +} /** * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped diff --git a/include/net/tcp.h b/include/net/tcp.h index aa04b9a..a144914 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -294,6 +294,7 @@ extern struct proto tcp_prot; #define TCP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field) #define TCP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->mib.tcp_statistics, field) #define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val) +#define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) extern void tcp_v4_err(struct sk_buff *skb, u32); @@ -423,7 +424,7 @@ extern u8 *tcp_parse_md5sig_option(struct tcphdr *th); * TCP v4 functions exported for the inet6 API */ -extern void tcp_v4_send_check(struct sock *sk, int len, +extern void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); extern int tcp_v4_conn_request(struct sock *sk, @@ -939,7 +940,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) tp->ucopy.memory = 0; } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) { - wake_up_interruptible_sync_poll(sk->sk_sleep, + wake_up_interruptible_sync_poll(sk_sleep(sk), POLLIN | POLLRDNORM | POLLRDBAND); if (!inet_csk_ack_scheduled(sk)) inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, @@ -1032,6 +1033,14 @@ static inline int keepalive_probes(const struct tcp_sock *tp) return tp->keepalive_probes ? : sysctl_tcp_keepalive_probes; } +static inline u32 keepalive_time_elapsed(const struct tcp_sock *tp) +{ + const struct inet_connection_sock *icsk = &tp->inet_conn; + + return min_t(u32, tcp_time_stamp - icsk->icsk_ack.lrcvtime, + tcp_time_stamp - tp->rcv_tstamp); +} + static inline int tcp_fin_time(const struct sock *sk) { int fin_timeout = tcp_sk(sk)->linger2 ? : sysctl_tcp_fin_timeout; diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h index 9566608..15af6dc 100644 --- a/include/net/tipc/tipc.h +++ b/include/net/tipc/tipc.h @@ -2,7 +2,7 @@ * include/net/tipc/tipc.h: Main include file for TIPC users * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005,2010 Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -126,7 +126,7 @@ int tipc_createport(unsigned int tipc_user, 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 */ + tipc_continue_event continue_event_cb, u32 *portref); int tipc_deleteport(u32 portref); @@ -145,13 +145,13 @@ 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 */ + struct tipc_name_seq const *name_seq); 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_shutdown(u32 ref); int tipc_isconnected(u32 portref, int *isconnected); @@ -176,7 +176,7 @@ int tipc_send_buf(u32 portref, int tipc_send2name(u32 portref, struct tipc_name const *name, - u32 domain, /* 0:own zone */ + u32 domain, unsigned int num_sect, struct iovec const *msg_sect); @@ -188,7 +188,7 @@ int tipc_send_buf2name(u32 portref, int tipc_forward2name(u32 portref, struct tipc_name const *name, - u32 domain, /*0: own zone */ + u32 domain, unsigned int section_count, struct iovec const *msg_sect, struct tipc_portid const *origin, @@ -228,14 +228,14 @@ int tipc_forward_buf2port(u32 portref, int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, - u32 domain, /* 0:own zone */ + u32 domain, /* currently unused */ 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 */ + u32 domain, void *buf, unsigned int size); #endif diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index d65381c..42a0eb6 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -44,7 +44,8 @@ extern int datagram_send_ctl(struct net *net, struct msghdr *msg, struct flowi *fl, struct ipv6_txoptions *opt, - int *hlimit, int *tclass); + int *hlimit, int *tclass, + int *dontfrag); #define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) diff --git a/include/net/x25.h b/include/net/x25.h index 468551e..1479cb4 100644 --- a/include/net/x25.h +++ b/include/net/x25.h @@ -80,8 +80,6 @@ enum { #define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */ #define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */ #define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */ -#define X25_DENY_ACCPT_APPRV 0x01 /* Default value */ -#define X25_ALLOW_ACCPT_APPRV 0x00 /* Control enabled */ #define X25_SMODULUS 8 #define X25_EMODULUS 128 @@ -113,6 +111,11 @@ enum { #define X25_MAX_AE_LEN 40 /* Max num of semi-octets in AE - OSI Nw */ #define X25_MAX_DTE_FACIL_LEN 21 /* Max length of DTE facility params */ +/* Bitset in x25_sock->flags for misc flags */ +#define X25_Q_BIT_FLAG 0 +#define X25_INTERRUPT_FLAG 1 +#define X25_ACCPT_APPRV_FLAG 2 + /** * struct x25_route - x25 routing entry * @node - entry in x25_list_lock @@ -146,10 +149,11 @@ struct x25_sock { struct x25_address source_addr, dest_addr; struct x25_neigh *neighbour; unsigned int lci, cudmatchlength; - unsigned char state, condition, qbitincl, intflag, accptapprv; + unsigned char state, condition; unsigned short vs, vr, va, vl; unsigned long t2, t21, t22, t23; unsigned short fraglen; + unsigned long flags; struct sk_buff_head ack_queue; struct sk_buff_head fragment_queue; struct sk_buff_head interrupt_in_queue; diff --git a/include/net/x25device.h b/include/net/x25device.h index 1415bcf..1fa08b4 100644 --- a/include/net/x25device.h +++ b/include/net/x25device.h @@ -3,6 +3,7 @@ #include <linux/if_ether.h> #include <linux/if_packet.h> +#include <linux/if_x25.h> #include <linux/skbuff.h> static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index ac52f33..1913af6 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -20,6 +20,7 @@ #include <net/route.h> #include <net/ipv6.h> #include <net/ip6_fib.h> +#include <net/flow.h> #include <linux/interrupt.h> @@ -267,7 +268,6 @@ struct xfrm_policy_afinfo { xfrm_address_t *saddr, xfrm_address_t *daddr); int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr); - struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy); void (*decode_session)(struct sk_buff *skb, struct flowi *fl, int reverse); @@ -482,13 +482,14 @@ struct xfrm_policy { atomic_t refcnt; struct timer_list timer; + struct flow_cache_object flo; + atomic_t genid; u32 priority; u32 index; struct xfrm_mark mark; struct xfrm_selector selector; struct xfrm_lifetime_cfg lft; struct xfrm_lifetime_cur curlft; - struct dst_entry *bundles; struct xfrm_policy_walk_entry walk; u8 type; u8 action; @@ -735,19 +736,12 @@ static inline void xfrm_pol_put(struct xfrm_policy *policy) xfrm_policy_destroy(policy); } -#ifdef CONFIG_XFRM_SUB_POLICY static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) { int i; for (i = npols - 1; i >= 0; --i) xfrm_pol_put(pols[i]); } -#else -static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) -{ - xfrm_pol_put(pols[0]); -} -#endif extern void __xfrm_state_destroy(struct xfrm_state *); @@ -878,11 +872,15 @@ struct xfrm_dst { struct rt6_info rt6; } u; struct dst_entry *route; + struct flow_cache_object flo; + struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; + int num_pols, num_xfrms; #ifdef CONFIG_XFRM_SUB_POLICY struct flowi *origin; struct xfrm_selector *partner; #endif - u32 genid; + u32 xfrm_genid; + u32 policy_genid; u32 route_mtu_cached; u32 child_mtu_cached; u32 route_cookie; @@ -892,6 +890,7 @@ struct xfrm_dst { #ifdef CONFIG_XFRM static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) { + xfrm_pols_put(xdst->pols, xdst->num_pols); dst_release(xdst->route); if (likely(xdst->u.dst.xfrm)) xfrm_state_put(xdst->u.dst.xfrm); |