* [PATCH net-next-2.6 v3 03/12] net-caif: add CAIF core protocol stack header files
From: sjur.brandeland @ 2010-02-22 22:05 UTC (permalink / raw)
To: netdev, davem, marcel
Cc: daniel.martensson, kaber, stefano.babic, randy.dunlap,
Sjur Braendeland
In-Reply-To: <1266876331-23988-3-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Add include files for the CAIF Core protocol stack.
caif_layer.h - Defines the structure of the CAIF protocol layers
cfcnfg.h - CAIF Configuration Module for services and link layers
cfctrl.h - CAIF Control Protocol Layer
cffrml.h - CAIF Framing Layer
cfmuxl.h - CAIF Muxing Layer
cfpkt.h - CAIF Packet layer (skb helper functions)
cfserl.h - CAIF Serial Layer
cfsrvl.h - CAIF Service Layer
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/net/caif/caif_layer.h | 283 +++++++++++++++++++++++++++++++++++++++++
include/net/caif/cfcnfg.h | 134 +++++++++++++++++++
include/net/caif/cfctrl.h | 136 ++++++++++++++++++++
include/net/caif/cffrml.h | 17 +++
include/net/caif/cfmuxl.h | 22 +++
include/net/caif/cfpkt.h | 274 +++++++++++++++++++++++++++++++++++++++
include/net/caif/cfserl.h | 13 ++
include/net/caif/cfsrvl.h | 34 +++++
8 files changed, 913 insertions(+), 0 deletions(-)
diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h
new file mode 100644
index 0000000..5732ad0
--- /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 layer;
+struct cfpkt;
+struct cfpktq;
+struct 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 layer - 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 layer {
+ struct layer *up;
+ struct layer *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 layer *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 layer *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 layer *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 layer *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 layer *)(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 layer *)(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 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 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..57ad876
--- /dev/null
+++ b/include/net/caif/cfcnfg.h
@@ -0,0 +1,134 @@
+/*
+ * 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 layer *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 layer *phy_layer);
+
+
+/**
+ * cfcnfg_del_adapt_layer - Deletes an adaptation layer from the CAIF stack.
+ *
+ * @cnfg: Pointer to a CAIF configuration object, created by
+ * cfcnfg_create().
+ * @adap_layer: Adaptation layer to be removed.
+ */
+int cfcnfg_del_adapt_layer(struct cfcnfg *cnfg, struct layer *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 layer *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..302e5a2
--- /dev/null
+++ b/include/net/caif/cfctrl.h
@@ -0,0 +1,136 @@
+/*
+ * 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 layer *layer, u8 linkid,
+ enum cfctrl_srv serv, u8 phyid,
+ struct layer *adapt_layer);
+ void (*linkdestroy_rsp)(struct layer *layer, u8 linkid,
+ struct layer *client_layer);
+ 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 layer *layer, u8 linkid,
+ struct layer *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 layer *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;
+ spinlock_t info_list_lock;
+#ifndef CAIF_NO_LOOP
+ u8 loop_linkid;
+ int loop_linkused[256];
+ spinlock_t loop_linkid_lock;
+#endif
+
+};
+
+void cfctrl_enum_req(struct layer *cfctrl, u8 physlinkid);
+void cfctrl_linkup_request(struct layer *cfctrl,
+ struct cfctrl_link_param *param,
+ struct layer *user_layer);
+int cfctrl_linkdown_req(struct layer *cfctrl, u8 linkid,
+ struct layer *client);
+void cfctrl_sleep_req(struct layer *cfctrl);
+void cfctrl_wake_req(struct layer *cfctrl);
+void cfctrl_getstartreason_req(struct layer *cfctrl);
+struct layer *cfctrl_create(void);
+void cfctrl_set_dnlayer(struct layer *this, struct layer *dn);
+void cfctrl_set_uplayer(struct layer *this, struct layer *up);
+struct cfctrl_rsp *cfctrl_get_respfuncs(struct layer *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);
+#endif /* CFCTRL_H_ */
diff --git a/include/net/caif/cffrml.h b/include/net/caif/cffrml.h
new file mode 100644
index 0000000..5412598
--- /dev/null
+++ b/include/net/caif/cffrml.h
@@ -0,0 +1,17 @@
+/*
+ * 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 layer *cffrml_create(u16 phyid, bool DoFCS);
+void cffrml_set_uplayer(struct layer *this, struct layer *up);
+void cffrml_set_dnlayer(struct layer *this, struct layer *dn);
+void cffrml_destroy(struct layer *layer);
+
+#endif /* CFFRML_H_ */
diff --git a/include/net/caif/cfmuxl.h b/include/net/caif/cfmuxl.h
new file mode 100644
index 0000000..16253bf
--- /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 layer *cfmuxl_create(void);
+int cfmuxl_set_uplayer(struct layer *layr, struct layer *up, u8 linkid);
+struct layer *cfmuxl_remove_dnlayer(struct layer *layr, u8 phyid);
+int cfmuxl_set_dnlayer(struct layer *layr, struct layer *up, u8 phyid);
+struct layer *cfmuxl_remove_uplayer(struct layer *layr, u8 linkid);
+bool cfmuxl_is_phy_inuse(struct layer *layr, u8 phyid);
+u8 cfmuxl_get_phyid(struct layer *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..93d8835
--- /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 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..fd0ec77
--- /dev/null
+++ b/include/net/caif/cfserl.h
@@ -0,0 +1,13 @@
+/*
+ * 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 layer *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..ddbe52b
--- /dev/null
+++ b/include/net/caif/cfsrvl.h
@@ -0,0 +1,34 @@
+/*
+ * 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>
+struct cfsrvl {
+ struct layer layer;
+ bool open;
+ bool phy_flow_on;
+ bool modem_flow_on;
+ struct dev_info dev_info;
+};
+
+struct layer *cfvei_create(u8 linkid, struct dev_info *dev_info);
+struct layer *cfdgml_create(u8 linkid, struct dev_info *dev_info);
+struct layer *cfutill_create(u8 linkid, struct dev_info *dev_info);
+struct layer *cfvidl_create(u8 linkid, struct dev_info *dev_info);
+struct layer *cfrfml_create(u8 linkid, struct dev_info *dev_info);
+struct layer *cfdbgl_create(u8 linkid, struct dev_info *dev_info);
+bool cfsrvl_phyid_match(struct layer *layer, int phyid);
+void cfservl_destroy(struct layer *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 layer *layer);
+
+#endif /* CFSRVL_H_ */
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 v3 02/12] net-caif: add CAIF socket and configuration headers
From: sjur.brandeland @ 2010-02-22 22:05 UTC (permalink / raw)
To: netdev, davem, marcel
Cc: daniel.martensson, kaber, stefano.babic, randy.dunlap,
Sjur Braendeland
In-Reply-To: <1266876331-23988-2-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changes from PATCHv2:
- Removed ifdef __cplusplus from caif_socket.h
- Removed caif_config.h containing legacy channel configuration types.
Add CAIF types for Socket Address, Socket Options,
and configuration parameters for the GPRS IP network interface.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/linux/caif/caif_socket.h | 188 ++++++++++++++++++++++++++++++++++++++
include/linux/caif/if_caif.h | 34 +++++++
2 files changed, 222 insertions(+), 0 deletions(-)
diff --git a/include/linux/caif/caif_socket.h b/include/linux/caif/caif_socket.h
new file mode 100644
index 0000000..f0aea0a
--- /dev/null
+++ b/include/linux/caif/caif_socket.h
@@ -0,0 +1,188 @@
+/* linux/caif_socket.h
+ * CAIF Definitions for CAIF socket and network layer
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/ sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef _LINUX_CAIF_SOCKET_H
+#define _LINUX_CAIF_SOCKET_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/socket.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+
+/**
+ * enum caif_link_selector - Physical Link Selection.
+ * @CAIF_LINK_HIGH_BANDW: Physical interface for high-bandwidth
+ * traffic.
+ * @CAIF_LINK_LOW_LATENCY: Physical interface for low-latency
+ * traffic.
+ *
+ * CAIF Link Layers can register their link properties.
+ * This enum is used for choosing between CAIF Link Layers when
+ * setting up CAIF Channels when multiple CAIF Link Layers exists.
+ */
+enum caif_link_selector {
+ CAIF_LINK_HIGH_BANDW,
+ CAIF_LINK_LOW_LATENCY
+};
+
+/**
+ * enum caif_channel_priority - CAIF channel priorities.
+ *
+ * @CAIF_PRIO_MIN: Min priority for a channel.
+ * @CAIF_PRIO_LOW: Low-priority channel.
+ * @CAIF_PRIO_NORMAL: Normal/default priority level.
+ * @CAIF_PRIO_HIGH: High priority level
+ * @CAIF_PRIO_MAX: Max priority for channel
+ *
+ * Priority can be set on CAIF Channels in order to
+ * prioritize between traffic on different CAIF Channels.
+ * These priority levels are recommended, but the priority value
+ * is not restricted to the values defined in this enum, any value
+ * between CAIF_PRIO_MIN and CAIF_PRIO_MAX could be used.
+ */
+enum caif_channel_priority {
+ CAIF_PRIO_MIN = 0x01,
+ CAIF_PRIO_LOW = 0x04,
+ CAIF_PRIO_NORMAL = 0x0f,
+ CAIF_PRIO_HIGH = 0x14,
+ CAIF_PRIO_MAX = 0x1F
+};
+
+/**
+ * enum caif_protocol_type - CAIF Channel type.
+ * @CAIFPROTO_AT: Classic AT channel.
+ * @CAIFPROTO_DATAGRAM: Datagram channel.
+ * @CAIFPROTO_DATAGRAM_LOOP: Datagram loopback channel, used for testing.
+ * @CAIFPROTO_UTIL: Utility (Psock) channel.
+ * @CAIFPROTO_RFM: Remote File Manager
+ *
+ * This enum defines the CAIF Channel type to be used. This defines
+ * the service to connect to on the modem.
+ */
+enum caif_protocol_type {
+ CAIFPROTO_AT,
+ CAIFPROTO_DATAGRAM,
+ CAIFPROTO_DATAGRAM_LOOP,
+ CAIFPROTO_UTIL,
+ CAIFPROTO_RFM,
+ _CAIFPROTO_MAX
+};
+#define CAIFPROTO_MAX _CAIFPROTO_MAX
+
+/**
+ * enum caif_at_type - AT Service Endpoint
+ * @CAIF_ATTYPE_PLAIN: Connects to a plain vanilla AT channel.
+ */
+enum caif_at_type {
+ CAIF_ATTYPE_PLAIN = 2
+};
+
+/**
+ * struct sockaddr_caif - the sockaddr structure for CAIF sockets.
+ * @u: Union of address data 'switched' by family.
+ * :
+ * @u.at: Applies when family = CAIFPROTO_AT.
+ *
+ * @u.at.type: Type of AT link to set up (enum caif_at_type).
+ *
+ * @u.util: Applies when family = CAIFPROTO_UTIL
+ *
+ * @u.util.service: Utility service name.
+ *
+ * @u.dgm: Applies when family = CAIFPROTO_DATAGRAM
+ *
+ * @u.dgm.connection_id: Datagram connection id.
+ *
+ * @u.dgm.nsapi: NSAPI of the PDP-Context.
+ *
+ * @u.rfm: Applies when family = CAIFPROTO_RFM
+ *
+ * @u.rfm.connection_id: Connection ID for RFM.
+ *
+ * @u.rfm.volume: Volume to mount.
+ *
+ * Description:
+ * This structure holds the connect parameters used for setting up a
+ * CAIF Channel. It defines the service to connect to on the modem.
+ */
+struct sockaddr_caif {
+ sa_family_t family;
+ union {
+ struct {
+ u_int8_t type; /* type: enum caif_at_type */
+ } at; /* CAIFPROTO_AT */
+ struct {
+ char service[16];
+ } util; /* CAIFPROTO_UTIL */
+ union {
+ u_int32_t connection_id;
+ u_int8_t nsapi;
+ } dgm; /* CAIFPROTO_DATAGRAM(_LOOP)*/
+ struct {
+ u_int32_t connection_id;
+ char volume[16];
+ } rfm; /* CAIFPROTO_RFM */
+ } u;
+};
+
+/**
+ * struct caif_param - CAIF parameters.
+ * @size: Length of data
+ * @data: Binary Data Blob
+ */
+struct caif_param {
+ u_int16_t size;
+ u_int8_t data[256];
+};
+
+/**
+ * enum caif_socket_opts - CAIF option values for getsockopt and setsockopt.
+ *
+ * @CAIFSO_LINK_SELECT: Selector used if multiple CAIF Link layers are
+ * available. Either a high bandwidth
+ * link can be selected (CAIF_LINK_HIGH_BANDW) or
+ * or a low latency link (CAIF_LINK_LOW_LATENCY).
+ * This option is of type u_int32_t.
+ * Alternatively SO_BINDTODEVICE can be used.
+ *
+ * @CAIFSO_REQ_PARAM: Used to set the request parameters for a
+ * utility channel. (struct caif_param). This
+ * option must be set before connecting.
+ *
+ * @CAIFSO_RSP_PARAM: Gets the request parameters for a utility
+ * channel. (struct caif_param). This option
+ * is valid after a successful connect.
+ *
+ * @CAIFSO_CHANNEL_ID: Gets the channel id on a CAIF Channel.
+ * This option is valid after a successful connect.
+ * ( u_int32_t)
+ *
+ * @CAIFSO_NEXT_PAKCET_LEN: Gets the size of next received packet.
+ * Value is 0 if no packet is available.
+ * This option is valid after a successful connect.
+ * ( u_int32_t)
+ *
+ * @CAIFSO_MAX_PAKCET_LEN: Gets the maximum packet size for this
+ * connection. ( u_int32_t)
+ *
+ * This enum defines the CAIF Socket options to be used on a socket
+ *
+ */
+enum caif_socket_opts {
+ CAIFSO_LINK_SELECT = 127,
+ CAIFSO_REQ_PARAM = 128,
+ CAIFSO_RSP_PARAM = 129,
+ CAIFSO_CHANNEL_ID = 130,
+ CAIFSO_NEXT_PACKET_LEN = 131,
+ CAIFSO_MAX_PACKET_LEN = 132,
+};
+
+#endif /* _LINUX_CAIF_SOCKET_H */
diff --git a/include/linux/caif/if_caif.h b/include/linux/caif/if_caif.h
new file mode 100644
index 0000000..5e7eed4
--- /dev/null
+++ b/include/linux/caif/if_caif.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland/ sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef IF_CAIF_H_
+#define IF_CAIF_H_
+#include <linux/sockios.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+
+/**
+ * enum ifla_caif - CAIF NetlinkRT parameters.
+ * @IFLA_CAIF_IPV4_CONNID: Connection ID for IPv4 PDP Context.
+ * The type of attribute is NLA_U32.
+ * @IFLA_CAIF_IPV6_CONNID: Connection ID for IPv6 PDP Context.
+ * The type of attribute is NLA_U32.
+ * @IFLA_CAIF_LOOPBACK: If different from zero, device is doing loopback
+ * The type of attribute is NLA_U8.
+ *
+ * When using RT Netlink to create, destroy or configure a CAIF IP interface,
+ * enum ifla_caif is used to specify the configuration attributes.
+ */
+enum ifla_caif {
+ __IFLA_CAIF_UNSPEC,
+ IFLA_CAIF_IPV4_CONNID,
+ IFLA_CAIF_IPV6_CONNID,
+ IFLA_CAIF_LOOPBACK,
+ __IFLA_CAIF_MAX
+};
+#define IFLA_CAIF_MAX (__IFLA_CAIF_MAX-1)
+
+#endif /*IF_CAIF_H_*/
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 v3 01/12] net-caif: add CAIF protocol definitions
From: sjur.brandeland @ 2010-02-22 22:05 UTC (permalink / raw)
To: netdev, davem, marcel
Cc: daniel.martensson, kaber, stefano.babic, randy.dunlap,
Sjur Braendeland
In-Reply-To: <1266876331-23988-1-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Add CAIF definitions to existing header files.
Files: if_arp.h, if_ether.h, socket.h.
Types: ARPHRD_CAIF, ETH_P_CAIF, AF_CAIF, PF_CAIF, SOL_CAIF, N_CAIF
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/linux/if_arp.h | 1 +
include/linux/if_ether.h | 1 +
include/linux/socket.h | 5 ++++-
3 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index e80b7f8..6d722f4 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -90,6 +90,7 @@
#define ARPHRD_PHONET 820 /* PhoNet media type */
#define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */
+#define ARPHRD_CAIF 822 /* CAIF media type */
#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
#define ARPHRD_NONE 0xFFFE /* zero header length */
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 299b412..bed7a46 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -109,6 +109,7 @@
#define ETH_P_TRAILER 0x001C /* Trailer switch tagging */
#define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */
#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */
+#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */
/*
* This is an Ethernet frame header.
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 7b3aae2..960659b 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -189,7 +189,8 @@ struct ucred {
#define AF_ISDN 34 /* mISDN sockets */
#define AF_PHONET 35 /* Phonet sockets */
#define AF_IEEE802154 36 /* IEEE802154 sockets */
-#define AF_MAX 37 /* For now.. */
+#define AF_CAIF 37 /* CAIF sockets */
+#define AF_MAX 38 /* For now.. */
/* Protocol families, same as address families. */
#define PF_UNSPEC AF_UNSPEC
@@ -229,6 +230,7 @@ struct ucred {
#define PF_ISDN AF_ISDN
#define PF_PHONET AF_PHONET
#define PF_IEEE802154 AF_IEEE802154
+#define PF_CAIF AF_CAIF
#define PF_MAX AF_MAX
/* Maximum queue length specifiable by listen. */
@@ -300,6 +302,7 @@ struct ucred {
#define SOL_PNPIPE 275
#define SOL_RDS 276
#define SOL_IUCV 277
+#define SOL_CAIF 278
/* IPX options */
#define IPX_TYPE 1
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 v3 00/12] net-caif: introducing CAIF protocol stack
From: sjur.brandeland @ 2010-02-22 22:05 UTC (permalink / raw)
To: netdev, davem, marcel
Cc: daniel.martensson, kaber, stefano.babic, randy.dunlap,
Sjur Braendeland
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
This patch-set introduces the CAIF protocol Stack.
The "Communication CPU to Application CPU Interface" (CAIF) is a packet based
connection-oriented MUX protocol developed by ST-Ericsson for use with its
modems.
CHANGE LOG:
Based on review comments from David Miller and Marcel Holtmann on the
previous patch set submitted the 16 February the following changes
have been done:
- Removed ifdef __cplusplus from caif_socket.h
- Use socket level SOL_IP for socket options SO_PRIORITY and SO_BINDTODEVICE
- Removed duplication of channel configuration by removing caif_config.h
- Bug fixes in caif_socket.c
OVERVIEW:
* CAIF provides a socket interface which can be used to open virtual AT
channels, create and configure GPRS Data connections.
* A CAIF Network device is also provided for GPRS access.
This interface can be managed with RTNL.
* A kernel interface is provided allowing Kernel modules to use CAIF.
* A serial link layer layer implemented as a line discipline is currently
implemented. Other link interfaces may be contributed at a later stage.
RTNL
!
! +------+ +------+ +------+
! +------+! +------+! +------+!
! ! Sock !! !Kernel!! ! Net !!
! ! API !+ ! API !+ ! Dev !+ <- CAIF "Client" APIs
! +------+ +------! +------+
! ! ! !
! +----------!----------+
! +------+ <- CAIF Core Protocol Implementation
+-------> ! CAIF !
! Core !
+------+
+--------!--------+
! !
+------+ +-----+
! ldisc! ! ... ! <- Link Layer (Net Devices)
+------+ +-----+
!
+------+
! tty !
+------+
Please see Documentation/networking/CAIF for more documentation.
Based on net-next-2.6
Sjur Braendeland (12):
net-caif: add CAIF protocol definitions
net-caif: add CAIF socket and configuration headers
net-caif: add CAIF core protocol stack header files
net-caif: add CAIF Link layer device header files
net-caif: add CAIF core protocol stack
net-caif: add CAIF generic caif support functions
net-caif: add CAIF device registration functionality
net-caif: add CAIF socket implementation
net-caif: add CAIF netdevice
net-caif: add CAIF Kconfig and Makefiles
net-caif: add CAIF documentation
net-caif-driver: add CAIF serial driver (ldisc)
Documentation/networking/caif/Linux-CAIF.txt | 212 ++++
Documentation/networking/caif/README | 110 ++
drivers/net/Kconfig | 2 +
drivers/net/Makefile | 1 +
drivers/net/caif/Kconfig | 24 +
drivers/net/caif/Makefile | 14 +
drivers/net/caif/caif_serial.c | 463 ++++++++
include/linux/caif/caif_socket.h | 188 ++++
include/linux/caif/if_caif.h | 34 +
include/linux/if_arp.h | 1 +
include/linux/if_ether.h | 1 +
include/linux/socket.h | 5 +-
include/linux/tty.h | 4 +-
include/net/caif/caif_dev.h | 81 ++
include/net/caif/caif_device.h | 57 +
include/net/caif/caif_layer.h | 283 +++++
include/net/caif/cfcnfg.h | 134 +++
include/net/caif/cfctrl.h | 136 +++
include/net/caif/cffrml.h | 17 +
include/net/caif/cfmuxl.h | 22 +
include/net/caif/cfpkt.h | 274 +++++
include/net/caif/cfserl.h | 13 +
include/net/caif/cfsrvl.h | 34 +
net/Kconfig | 2 +
net/Makefile | 1 +
net/caif/Kconfig | 48 +
net/caif/Makefile | 28 +
net/caif/caif_config_util.c | 88 ++
net/caif/caif_dev.c | 394 +++++++
net/caif/caif_socket.c | 1462 ++++++++++++++++++++++++++
net/caif/cfcnfg.c | 529 ++++++++++
net/caif/cfctrl.c | 710 +++++++++++++
net/caif/cfdbgl.c | 40 +
net/caif/cfdgml.c | 108 ++
net/caif/cffrml.c | 151 +++
net/caif/cfmuxl.c | 246 +++++
net/caif/cfpkt_skbuff.c | 595 +++++++++++
net/caif/cfrfml.c | 106 ++
net/caif/cfserl.c | 199 ++++
net/caif/cfsrvl.c | 185 ++++
net/caif/cfutill.c | 115 ++
net/caif/cfveil.c | 107 ++
net/caif/cfvidl.c | 65 ++
net/caif/chnl_net.c | 429 ++++++++
44 files changed, 7715 insertions(+), 3 deletions(-)
^ permalink raw reply
* Re: RFC: netfilter: nf_conntrack: add support for "conntrack zones"
From: jamal @ 2010-02-22 21:55 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Patrick McHardy, Linux Netdev List, containers,
Netfilter Development Mailinglist, Ben Greear
In-Reply-To: <m13a0tf17t.fsf@fess.ebiederm.org>
On Mon, 2010-02-22 at 12:46 -0800, Eric W. Biederman wrote:
> jamal <hadi@cyberus.ca> writes:
>
> This is one of the long standing issues that we have always known
> we needed to solve, but have not taken the time to do it. Now that
> the need is more real it looks about time to solve this one.
>
> There are currently two problems.
> 1) A process is needed to hold a reference to the network namespace.
> 2) We use pids which are an awkward way of talking about network
> namespaces.
>
> The solution I have been playing with involves.
> - Using a file descriptor to refer to a network namespace.
> - Using a trivial virtual filesystem to persistently hold onto
> a namespace without the need of a process.
> - Have a convention of mounting the fs at something like
> /var/run/netns/<name>
>
I didnt quiet follow how i could use the above to do:
"ip ns <name/id> route add blah" from namespace0.
I tend to think in packets and wires instead of files;
How about just allowing a "control" channel from which
i could discover the namespace?
Example, assuming i have the right permissions:
1) listen to async events example on a multicast bus when
a namespace is created or destroyed. Provide me a little more info on
the created namespace such as its pid, name(?), types of namespace, etc
2) send a query to dump existing namespace or query by name, id etc.
I get the same details as above.
using genetlink should provide you with sufficient ability to do this.
cheers,
jamal
^ permalink raw reply
* [net-next-2.6 PATCH 7/7] xfrm: Allow user space manipulation of SPD mark
From: jamal @ 2010-02-22 21:33 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <1266874380-29593-7-git-send-email-hadi@cyberus.ca>
From: Jamal Hadi Salim <hadi@cyberus.ca>
Add ability for netlink userspace to manipulate the SPD
and manipulate the mark, retrieve it and get events with a defined
mark, etc.
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
net/xfrm/xfrm_user.c | 31 +++++++++++++++++++++++++------
1 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 303092f..6106b72 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -31,8 +31,6 @@
#include <linux/in6.h>
#endif
-#define DUMMY_MARK 0
-
static inline int aead_len(struct xfrm_algo_aead *alg)
{
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -1234,6 +1232,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us
if (err)
goto error;
+ xfrm_mark_get(attrs, &xp->mark);
+
return xp;
error:
*errp = err;
@@ -1380,10 +1380,13 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
goto nlmsg_failure;
if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
+ if (xfrm_mark_put(skb, &xp->mark))
+ goto nla_put_failure;
nlmsg_end(skb, nlh);
return 0;
+nla_put_failure:
nlmsg_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
@@ -1455,6 +1458,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
int err;
struct km_event c;
int delete;
+ struct xfrm_mark m;
+ u32 mark = xfrm_mark_get(attrs, &m);
p = nlmsg_data(nlh);
delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;
@@ -1468,7 +1473,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
return err;
if (p->index)
- xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, delete, &err);
+ xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_sec_ctx *ctx;
@@ -1485,7 +1490,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err)
return err;
}
- xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel,
+ xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel,
ctx, delete, &err);
security_xfrm_policy_free(ctx);
}
@@ -1729,13 +1734,15 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_userpolicy_info *p = &up->pol;
u8 type = XFRM_POLICY_TYPE_MAIN;
int err = -ENOENT;
+ struct xfrm_mark m;
+ u32 mark = xfrm_mark_get(attrs, &m);
err = copy_from_user_policy_type(&type, attrs);
if (err)
return err;
if (p->index)
- xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, 0, &err);
+ xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_sec_ctx *ctx;
@@ -1752,7 +1759,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err)
return err;
}
- xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir,
+ xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir,
&p->sel, ctx, 0, &err);
security_xfrm_policy_free(ctx);
}
@@ -2424,9 +2431,12 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
goto nlmsg_failure;
if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
+ if (xfrm_mark_put(skb, &xp->mark))
+ goto nla_put_failure;
return nlmsg_end(skb, nlh);
+nla_put_failure:
nlmsg_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
@@ -2513,6 +2523,7 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp)
return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire))
+ nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
+ nla_total_size(xfrm_user_sec_ctx_size(xp->security))
+ + nla_total_size(sizeof(struct xfrm_mark))
+ userpolicy_type_attrsize();
}
@@ -2535,10 +2546,13 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
goto nlmsg_failure;
if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
+ if (xfrm_mark_put(skb, &xp->mark))
+ goto nla_put_failure;
upe->hard = !!hard;
return nlmsg_end(skb, nlh);
+nla_put_failure:
nlmsg_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
@@ -2575,6 +2589,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
headlen = sizeof(*id);
}
len += userpolicy_type_attrsize();
+ len += nla_total_size(sizeof(struct xfrm_mark));
len += NLMSG_ALIGN(headlen);
skb = nlmsg_new(len, GFP_ATOMIC);
@@ -2610,10 +2625,14 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
if (copy_to_user_policy_type(xp->type, skb) < 0)
goto nlmsg_failure;
+ if (xfrm_mark_put(skb, &xp->mark))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
+nla_put_failure:
nlmsg_failure:
kfree_skb(skb);
return -1;
--
1.6.0.4
^ permalink raw reply related
* [net-next-2.6 PATCH 6/7] xfrm: Allow user space config of SAD mark
From: jamal @ 2010-02-22 21:32 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <1266874380-29593-6-git-send-email-hadi@cyberus.ca>
From: Jamal Hadi Salim <hadi@cyberus.ca>
Add ability for netlink userspace to manipulate the SAD
and manipulate the mark, retrieve it and get events with a defined
mark.
MIGRATE may be added later.
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
net/xfrm/xfrm_user.c | 72 +++++++++++++++++++++++++++++++++++++++----------
1 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 02a67b4..303092f 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -32,7 +32,6 @@
#endif
#define DUMMY_MARK 0
-static struct xfrm_mark dummy_mark = {0, 0};
static inline int aead_len(struct xfrm_algo_aead *alg)
{
@@ -449,6 +448,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
goto error;
}
+ xfrm_mark_get(attrs, &x->mark);
+
err = xfrm_init_state(x);
if (err)
goto error;
@@ -529,11 +530,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
int *errp)
{
struct xfrm_state *x = NULL;
+ struct xfrm_mark m;
int err;
+ u32 mark = xfrm_mark_get(attrs, &m);
if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
err = -ESRCH;
- x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family);
+ x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family);
} else {
xfrm_address_t *saddr = NULL;
@@ -544,7 +547,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
}
err = -ESRCH;
- x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr,
+ x = xfrm_state_lookup_byaddr(net, mark,
+ &p->daddr, saddr,
p->proto, p->family);
}
@@ -686,6 +690,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
if (x->encap)
NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
+ if (xfrm_mark_put(skb, &x->mark))
+ goto nla_put_failure;
+
if (x->security && copy_sec_ctx(x->security, skb) < 0)
goto nla_put_failure;
@@ -950,6 +957,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
xfrm_address_t *daddr;
int family;
int err;
+ u32 mark;
+ struct xfrm_mark m;
p = nlmsg_data(nlh);
err = verify_userspi_info(p);
@@ -960,8 +969,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
daddr = &p->info.id.daddr;
x = NULL;
+
+ mark = xfrm_mark_get(attrs, &m);
if (p->info.seq) {
- x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq);
+ x = xfrm_find_acq_byseq(net, mark, p->info.seq);
if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
xfrm_state_put(x);
x = NULL;
@@ -969,7 +980,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
}
if (!x)
- x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid,
+ x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid,
p->info.id.proto, daddr,
&p->info.saddr, 1,
family);
@@ -1474,8 +1485,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err)
return err;
}
- xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir,
- &p->sel, ctx, delete, &err);
+ xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel,
+ ctx, delete, &err);
security_xfrm_policy_free(ctx);
}
if (xp == NULL)
@@ -1547,6 +1558,7 @@ static inline size_t xfrm_aevent_msgsize(void)
return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
+ nla_total_size(sizeof(struct xfrm_replay_state))
+ nla_total_size(sizeof(struct xfrm_lifetime_cur))
+ + nla_total_size(sizeof(struct xfrm_mark))
+ nla_total_size(4) /* XFRM_AE_RTHR */
+ nla_total_size(4); /* XFRM_AE_ETHR */
}
@@ -1579,6 +1591,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH,
x->replay_maxage * 10 / HZ);
+ if (xfrm_mark_put(skb, &x->mark))
+ goto nla_put_failure;
+
return nlmsg_end(skb, nlh);
nla_put_failure:
@@ -1594,6 +1609,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct sk_buff *r_skb;
int err;
struct km_event c;
+ u32 mark;
+ struct xfrm_mark m;
struct xfrm_aevent_id *p = nlmsg_data(nlh);
struct xfrm_usersa_id *id = &p->sa_id;
@@ -1601,7 +1618,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (r_skb == NULL)
return -ENOMEM;
- x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family);
+ mark = xfrm_mark_get(attrs, &m);
+
+ x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
if (x == NULL) {
kfree_skb(r_skb);
return -ESRCH;
@@ -1632,6 +1651,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_state *x;
struct km_event c;
int err = - EINVAL;
+ u32 mark = 0;
+ struct xfrm_mark m;
struct xfrm_aevent_id *p = nlmsg_data(nlh);
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
@@ -1643,7 +1664,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
return err;
- x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
+ mark = xfrm_mark_get(attrs, &m);
+
+ x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
if (x == NULL)
return -ESRCH;
@@ -1729,7 +1752,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err)
return err;
}
- xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ctx, 0, &err);
+ xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir,
+ &p->sel, ctx, 0, &err);
security_xfrm_policy_free(ctx);
}
if (xp == NULL)
@@ -1769,8 +1793,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
int err;
struct xfrm_user_expire *ue = nlmsg_data(nlh);
struct xfrm_usersa_info *p = &ue->state;
+ struct xfrm_mark m;
+ u32 mark = xfrm_mark_get(attrs, &m);;
- x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family);
+ x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family);
err = -ENOENT;
if (x == NULL)
@@ -1804,6 +1830,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_user_tmpl *ut;
int i;
struct nlattr *rt = attrs[XFRMA_TMPL];
+ struct xfrm_mark mark;
struct xfrm_user_acquire *ua = nlmsg_data(nlh);
struct xfrm_state *x = xfrm_state_alloc(net);
@@ -1812,6 +1839,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!x)
goto nomem;
+ xfrm_mark_get(attrs, &mark);
+
err = verify_newpolicy_info(&ua->policy);
if (err)
goto bad_policy;
@@ -1824,7 +1853,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
memcpy(&x->id, &ua->id, sizeof(ua->id));
memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr));
memcpy(&x->sel, &ua->sel, sizeof(ua->sel));
-
+ xp->mark.m = x->mark.m = mark.m;
+ xp->mark.v = x->mark.v = mark.v;
ut = nla_data(rt);
/* extract the templates and for each call km_key */
for (i = 0; i < xp->xfrm_nr; i++, ut++) {
@@ -2084,6 +2114,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)},
[XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) },
[XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
+ [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
};
static struct xfrm_link {
@@ -2163,7 +2194,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb)
static inline size_t xfrm_expire_msgsize(void)
{
- return NLMSG_ALIGN(sizeof(struct xfrm_user_expire));
+ return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
+ + nla_total_size(sizeof(struct xfrm_mark));
}
static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
@@ -2179,7 +2211,13 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
copy_to_user_state(x, &ue->state);
ue->hard = (c->data.hard != 0) ? 1 : 0;
+ if (xfrm_mark_put(skb, &x->mark))
+ goto nla_put_failure;
+
return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+ return -EMSGSIZE;
}
static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
@@ -2191,8 +2229,10 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
if (skb == NULL)
return -ENOMEM;
- if (build_expire(skb, x, c) < 0)
- BUG();
+ if (build_expire(skb, x, c) < 0) {
+ kfree_skb(skb);
+ return -EMSGSIZE;
+ }
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
}
@@ -2280,6 +2320,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
if (c->event == XFRM_MSG_DELSA) {
len += nla_total_size(headlen);
headlen = sizeof(*id);
+ len += nla_total_size(sizeof(struct xfrm_mark));
}
len += NLMSG_ALIGN(headlen);
@@ -2350,6 +2391,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x,
{
return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire))
+ nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
+ + nla_total_size(sizeof(struct xfrm_mark))
+ nla_total_size(xfrm_user_sec_ctx_size(x->security))
+ userpolicy_type_attrsize();
}
--
1.6.0.4
^ permalink raw reply related
* [net-next-2.6 PATCH 5/7] xfrm: SP lookups with mark
From: jamal @ 2010-02-22 21:32 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <1266874380-29593-5-git-send-email-hadi@cyberus.ca>
From: Jamal Hadi Salim <hadi@cyberus.ca>
Allow mark to be used when doing SP lookup
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
net/xfrm/xfrm_policy.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e67d3ca..2a6e646 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -556,6 +556,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
struct hlist_head *chain;
struct hlist_node *entry, *newpos;
struct dst_entry *gc_list;
+ u32 mark = policy->mark.v & policy->mark.m;
write_lock_bh(&xfrm_policy_lock);
chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
@@ -564,6 +565,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
hlist_for_each_entry(pol, entry, chain, bydst) {
if (pol->type == policy->type &&
!selector_cmp(&pol->selector, &policy->selector) &&
+ (mark & pol->mark.m) == pol->mark.v &&
xfrm_sec_ctx_match(pol->security, policy->security) &&
!WARN_ON(delpol)) {
if (excl) {
@@ -650,6 +652,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
ret = NULL;
hlist_for_each_entry(pol, entry, chain, bydst) {
if (pol->type == type &&
+ (mark & pol->mark.m) == pol->mark.v &&
!selector_cmp(sel, &pol->selector) &&
xfrm_sec_ctx_match(ctx, pol->security)) {
xfrm_pol_hold(pol);
@@ -692,7 +695,8 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
chain = net->xfrm.policy_byidx + idx_hash(net, id);
ret = NULL;
hlist_for_each_entry(pol, entry, chain, byidx) {
- if (pol->type == type && pol->index == id) {
+ if (pol->type == type && pol->index == id &&
+ (mark & pol->mark.m) == pol->mark.v) {
xfrm_pol_hold(pol);
if (delete) {
*err = security_xfrm_policy_delete(
@@ -916,6 +920,7 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
int match, ret = -ESRCH;
if (pol->family != family ||
+ (fl->mark & pol->mark.m) != pol->mark.v ||
pol->type != type)
return ret;
@@ -1040,6 +1045,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
int err = 0;
if (match) {
+ if ((sk->sk_mark & pol->mark.m) != pol->mark.v) {
+ pol = NULL;
+ goto out;
+ }
err = security_xfrm_policy_lookup(pol->security,
fl->secid,
policy_to_flow_dir(dir));
@@ -1052,6 +1061,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
} else
pol = NULL;
}
+out:
read_unlock_bh(&xfrm_policy_lock);
return pol;
}
--
1.6.0.4
^ permalink raw reply related
* [net-next-2.6 PATCH 4/7] xfrm: SP lookups signature with mark
From: jamal @ 2010-02-22 21:32 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <1266874380-29593-4-git-send-email-hadi@cyberus.ca>
From: Jamal Hadi Salim <hadi@cyberus.ca>
pass mark to all SP lookups to prepare them for when we add code
to have them search.
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
include/net/xfrm.h | 5 +++--
net/key/af_key.c | 4 ++--
net/xfrm/xfrm_policy.c | 8 ++++----
net/xfrm/xfrm_user.c | 10 +++++-----
4 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 693523c..a7df327 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1450,11 +1450,12 @@ extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
int (*func)(struct xfrm_policy *, int, int, void*), void *);
extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
-struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
+struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
+ u8 type, int dir,
struct xfrm_selector *sel,
struct xfrm_sec_ctx *ctx, int delete,
int *err);
-struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int delete, int *err);
+struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32 id, int delete, int *err);
int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 9194d48..4f89233 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2370,7 +2370,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
return err;
}
- xp = xfrm_policy_bysel_ctx(net, XFRM_POLICY_TYPE_MAIN,
+ xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN,
pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
1, &err);
security_xfrm_policy_free(pol_ctx);
@@ -2618,7 +2618,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return -EINVAL;
delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
- xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN,
+ xp = xfrm_policy_byid(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN,
dir, pol->sadb_x_policy_id, delete, &err);
if (xp == NULL)
return -ENOENT;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d6eb16d..e67d3ca 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -635,8 +635,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
}
EXPORT_SYMBOL(xfrm_policy_insert);
-struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
- struct xfrm_selector *sel,
+struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
+ int dir, struct xfrm_selector *sel,
struct xfrm_sec_ctx *ctx, int delete,
int *err)
{
@@ -676,8 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
}
EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
-struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id,
- int delete, int *err)
+struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
+ int dir, u32 id, int delete, int *err)
{
struct xfrm_policy *pol, *ret;
struct hlist_head *chain;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 331ae73..02a67b4 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1457,7 +1457,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
return err;
if (p->index)
- xp = xfrm_policy_byid(net, type, p->dir, p->index, delete, &err);
+ xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, delete, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_sec_ctx *ctx;
@@ -1474,8 +1474,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err)
return err;
}
- xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx,
- delete, &err);
+ xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir,
+ &p->sel, ctx, delete, &err);
security_xfrm_policy_free(ctx);
}
if (xp == NULL)
@@ -1712,7 +1712,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
return err;
if (p->index)
- xp = xfrm_policy_byid(net, type, p->dir, p->index, 0, &err);
+ xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, 0, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_sec_ctx *ctx;
@@ -1729,7 +1729,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err)
return err;
}
- xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, 0, &err);
+ xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ctx, 0, &err);
security_xfrm_policy_free(ctx);
}
if (xp == NULL)
--
1.6.0.4
^ permalink raw reply related
* [net-next-2.6 PATCH 3/7] xfrm: SA lookups with mark
From: jamal @ 2010-02-22 21:32 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <1266874380-29593-3-git-send-email-hadi@cyberus.ca>
From: Jamal Hadi Salim <hadi@cyberus.ca>
Allow mark to be added to the SA lookup
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
net/xfrm/xfrm_state.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9f85303..17d5b96 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -682,6 +682,8 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_ad
xfrm_addr_cmp(&x->id.daddr, daddr, family))
continue;
+ if ((mark & x->mark.m) != x->mark.v)
+ continue;
xfrm_state_hold(x);
return x;
}
@@ -702,6 +704,8 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
xfrm_addr_cmp(&x->props.saddr, saddr, family))
continue;
+ if ((mark & x->mark.m) != x->mark.v)
+ continue;
xfrm_state_hold(x);
return x;
}
@@ -794,6 +798,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
if (x->props.family == family &&
x->props.reqid == tmpl->reqid &&
+ (mark & x->mark.m) == x->mark.v &&
!(x->props.flags & XFRM_STATE_WILDRECV) &&
xfrm_state_addr_check(x, daddr, saddr, family) &&
tmpl->mode == x->props.mode &&
@@ -809,6 +814,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) {
if (x->props.family == family &&
x->props.reqid == tmpl->reqid &&
+ (mark & x->mark.m) == x->mark.v &&
!(x->props.flags & XFRM_STATE_WILDRECV) &&
xfrm_state_addr_check(x, daddr, saddr, family) &&
tmpl->mode == x->props.mode &&
@@ -892,6 +898,7 @@ xfrm_stateonly_find(struct net *net, u32 mark,
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
if (x->props.family == family &&
x->props.reqid == reqid &&
+ (mark & x->mark.m) == x->mark.v &&
!(x->props.flags & XFRM_STATE_WILDRECV) &&
xfrm_state_addr_check(x, daddr, saddr, family) &&
mode == x->props.mode &&
@@ -954,11 +961,13 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
struct xfrm_state *x;
struct hlist_node *entry;
unsigned int h;
+ u32 mark = xnew->mark.v & xnew->mark.m;
h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family);
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
if (x->props.family == family &&
x->props.reqid == reqid &&
+ (mark & x->mark.m) == x->mark.v &&
!xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
!xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
x->genid = xfrm_state_genid;
@@ -980,6 +989,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m,
unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
struct hlist_node *entry;
struct xfrm_state *x;
+ u32 mark = m->v & m->m;
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
if (x->props.reqid != reqid ||
@@ -988,6 +998,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m,
x->km.state != XFRM_STATE_ACQ ||
x->id.spi != 0 ||
x->id.proto != proto ||
+ (mark & x->mark.m) != x->mark.v ||
xfrm_addr_cmp(&x->id.daddr, daddr, family) ||
xfrm_addr_cmp(&x->props.saddr, saddr, family))
continue;
@@ -1442,6 +1453,7 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 s
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) {
if (x->km.seq == seq &&
+ (mark & x->mark.m) == x->mark.v &&
x->km.state == XFRM_STATE_ACQ) {
xfrm_state_hold(x);
return x;
--
1.6.0.4
^ permalink raw reply related
* [net-next-2.6 PATCH 2/7] xfrm: SA lookups signature with mark
From: jamal @ 2010-02-22 21:32 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <1266874380-29593-2-git-send-email-hadi@cyberus.ca>
From: Jamal Hadi Salim <hadi@cyberus.ca>
pass mark to all SA lookups to prepare them for when we add code
to have them search.
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
include/net/xfrm.h | 23 +++++++++++++-----
net/core/pktgen.c | 3 +-
net/ipv4/ah4.c | 2 +-
net/ipv4/esp4.c | 2 +-
net/ipv4/ipcomp.c | 6 +++-
net/ipv6/ah6.c | 2 +-
net/ipv6/esp6.c | 2 +-
net/ipv6/ipcomp6.c | 6 +++-
net/ipv6/xfrm6_input.c | 2 +-
net/key/af_key.c | 14 ++++++-----
net/xfrm/xfrm_input.c | 2 +-
net/xfrm/xfrm_state.c | 58 ++++++++++++++++++++++++++++-------------------
net/xfrm/xfrm_user.c | 17 ++++++++-----
13 files changed, 84 insertions(+), 55 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 39f151c..693523c 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1319,7 +1319,7 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t
struct flowi *fl, struct xfrm_tmpl *tmpl,
struct xfrm_policy *pol, int *err,
unsigned short family);
-extern struct xfrm_state * xfrm_stateonly_find(struct net *net,
+extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
xfrm_address_t *daddr,
xfrm_address_t *saddr,
unsigned short family,
@@ -1328,8 +1328,14 @@ extern int xfrm_state_check_expire(struct xfrm_state *x);
extern void xfrm_state_insert(struct xfrm_state *x);
extern int xfrm_state_add(struct xfrm_state *x);
extern int xfrm_state_update(struct xfrm_state *x);
-extern struct xfrm_state *xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family);
-extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
+ xfrm_address_t *daddr, __be32 spi,
+ u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr,
+ u8 proto,
+ unsigned short family);
#ifdef CONFIG_XFRM_SUB_POLICY
extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
int n, unsigned short family);
@@ -1366,7 +1372,8 @@ struct xfrmk_spdinfo {
u32 spdhmcnt;
};
-extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq);
+extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark,
+ u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
@@ -1451,9 +1458,11 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int d
int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
-struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto,
- xfrm_address_t *daddr, xfrm_address_t *saddr,
- int create, unsigned short family);
+struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
+ u8 mode, u32 reqid, u8 proto,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr, int create,
+ unsigned short family);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
struct flowi *fl, int family, int strict);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2e692af..4392381 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2188,12 +2188,13 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)
/* If there was already an IPSEC SA, we keep it as is, else
* we go look for it ...
*/
+#define DUMMY_MARK 0
static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
{
struct xfrm_state *x = pkt_dev->flows[flow].x;
if (!x) {
/*slow path: we dont already have xfrm_state*/
- x = xfrm_stateonly_find(&init_net,
+ x = xfrm_stateonly_find(&init_net, DUMMY_MARK,
(xfrm_address_t *)&pkt_dev->cur_daddr,
(xfrm_address_t *)&pkt_dev->cur_saddr,
AF_INET,
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 7ed3e4a..987b47d 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -393,7 +393,7 @@ static void ah4_err(struct sk_buff *skb, u32 info)
icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
return;
- x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET);
+ x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET);
if (!x)
return;
printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n",
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 1948895..14ca1f1 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -422,7 +422,7 @@ static void esp4_err(struct sk_buff *skb, u32 info)
icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
return;
- x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
+ x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
if (!x)
return;
NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n",
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 83ed715..6290675 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -36,7 +36,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
return;
spi = htonl(ntohs(ipch->cpi));
- x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr,
+ x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr,
spi, IPPROTO_COMP, AF_INET);
if (!x)
return;
@@ -63,6 +63,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
t->props.mode = x->props.mode;
t->props.saddr.a4 = x->props.saddr.a4;
t->props.flags = x->props.flags;
+ memcpy(&t->mark, &x->mark, sizeof(t->mark));
if (xfrm_init_state(t))
goto error;
@@ -87,8 +88,9 @@ static int ipcomp_tunnel_attach(struct xfrm_state *x)
struct net *net = xs_net(x);
int err = 0;
struct xfrm_state *t;
+ u32 mark = x->mark.v & x->mark.m;
- t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr.a4,
+ t = xfrm_state_lookup(net, mark, (xfrm_address_t *)&x->id.daddr.a4,
x->props.saddr.a4, IPPROTO_IPIP, AF_INET);
if (!t) {
t = ipcomp_tunnel_create(x);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index c2f300c..5ac8902 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -614,7 +614,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
type != ICMPV6_PKT_TOOBIG)
return;
- x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6);
+ x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6);
if (!x)
return;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 668a46b..ee9b93b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -365,7 +365,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
type != ICMPV6_PKT_TOOBIG)
return;
- x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
+ x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
if (!x)
return;
printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n",
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index bb42f39..85cccd6 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -64,7 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return;
spi = htonl(ntohs(ipcomph->cpi));
- x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6);
+ x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6);
if (!x)
return;
@@ -92,6 +92,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
t->props.family = AF_INET6;
t->props.mode = x->props.mode;
memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
+ memcpy(&t->mark, &x->mark, sizeof(t->mark));
if (xfrm_init_state(t))
goto error;
@@ -114,10 +115,11 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x)
int err = 0;
struct xfrm_state *t = NULL;
__be32 spi;
+ u32 mark = x->mark.m & x->mark.v;
spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&x->props.saddr);
if (spi)
- t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr,
+ t = xfrm_state_lookup(net, mark, (xfrm_address_t *)&x->id.daddr,
spi, IPPROTO_IPV6, AF_INET6);
if (!t) {
t = ipcomp6_tunnel_create(x);
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 9084582..2bc98ed 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -101,7 +101,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
break;
}
- x = xfrm_state_lookup_byaddr(net, dst, src, proto, AF_INET6);
+ x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6);
if (!x)
continue;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index a20d2fa..9194d48 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -45,6 +45,8 @@ static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait);
static DEFINE_RWLOCK(pfkey_table_lock);
static atomic_t pfkey_table_users = ATOMIC_INIT(0);
+#define DUMMY_MARK 0
+static struct xfrm_mark dummy_mark = {0, 0};
struct pfkey_sock {
/* struct sock must be the first member of struct pfkey_sock */
struct sock sk;
@@ -691,7 +693,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct net *net, struct sadb_
if (!xaddr)
return NULL;
- return xfrm_state_lookup(net, xaddr, sa->sadb_sa_spi, proto, family);
+ return xfrm_state_lookup(net, DUMMY_MARK, xaddr, sa->sadb_sa_spi, proto, family);
}
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
@@ -1360,7 +1362,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
}
if (hdr->sadb_msg_seq) {
- x = xfrm_find_acq_byseq(net, hdr->sadb_msg_seq);
+ x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) {
xfrm_state_put(x);
x = NULL;
@@ -1368,7 +1370,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
}
if (!x)
- x = xfrm_find_acq(net, mode, reqid, proto, xdaddr, xsaddr, 1, family);
+ x = xfrm_find_acq(net, &dummy_mark, mode, reqid, proto, xdaddr, xsaddr, 1, family);
if (x == NULL)
return -ENOENT;
@@ -1417,7 +1419,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0)
return 0;
- x = xfrm_find_acq_byseq(net, hdr->sadb_msg_seq);
+ x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
if (x == NULL)
return 0;
@@ -2616,8 +2618,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return -EINVAL;
delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
- xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN, dir,
- pol->sadb_x_policy_id, delete, &err);
+ xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN,
+ dir, pol->sadb_x_policy_id, delete, &err);
if (xp == NULL)
return -ENOENT;
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index e0009c1..45f1c98 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -152,7 +152,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop;
}
- x = xfrm_state_lookup(net, daddr, spi, nexthdr, family);
+ x = xfrm_state_lookup(net, skb->mark, daddr, spi, nexthdr, family);
if (x == NULL) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
xfrm_audit_state_notfound(skb, family, spi, seq);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9fa3322..9f85303 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -669,7 +669,7 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
return 0;
}
-static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
+static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
{
unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
struct xfrm_state *x;
@@ -689,7 +689,7 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
return NULL;
}
-static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
+static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
{
unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
struct xfrm_state *x;
@@ -713,12 +713,14 @@ static inline struct xfrm_state *
__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
{
struct net *net = xs_net(x);
+ u32 mark = x->mark.v & x->mark.m;
if (use_spi)
- return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi,
- x->id.proto, family);
+ return __xfrm_state_lookup(net, mark, &x->id.daddr,
+ x->id.spi, x->id.proto, family);
else
- return __xfrm_state_lookup_byaddr(net, &x->id.daddr,
+ return __xfrm_state_lookup_byaddr(net, mark,
+ &x->id.daddr,
&x->props.saddr,
x->id.proto, family);
}
@@ -783,6 +785,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
int acquire_in_progress = 0;
int error = 0;
struct xfrm_state *best = NULL;
+ u32 mark = pol->mark.v & pol->mark.m;
to_put = NULL;
@@ -819,7 +822,7 @@ found:
x = best;
if (!x && !error && !acquire_in_progress) {
if (tmpl->id.spi &&
- (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi,
+ (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
tmpl->id.proto, family)) != NULL) {
to_put = x0;
error = -EEXIST;
@@ -833,6 +836,7 @@ found:
/* Initialize temporary selector matching only
* to current session. */
xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
+ memcpy(&x->mark, &pol->mark, sizeof(x->mark));
error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
if (error) {
@@ -875,7 +879,7 @@ out:
}
struct xfrm_state *
-xfrm_stateonly_find(struct net *net,
+xfrm_stateonly_find(struct net *net, u32 mark,
xfrm_address_t *daddr, xfrm_address_t *saddr,
unsigned short family, u8 mode, u8 proto, u32 reqid)
{
@@ -971,7 +975,7 @@ void xfrm_state_insert(struct xfrm_state *x)
EXPORT_SYMBOL(xfrm_state_insert);
/* xfrm_state_lock is held */
-static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
+static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
{
unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
struct hlist_node *entry;
@@ -1026,6 +1030,8 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
x->props.family = family;
x->props.mode = mode;
x->props.reqid = reqid;
+ x->mark.v = m->v;
+ x->mark.m = m->m;
x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
xfrm_state_hold(x);
tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
@@ -1042,7 +1048,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
return x;
}
-static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq);
+static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
int xfrm_state_add(struct xfrm_state *x)
{
@@ -1050,6 +1056,7 @@ int xfrm_state_add(struct xfrm_state *x)
struct xfrm_state *x1, *to_put;
int family;
int err;
+ u32 mark = x->mark.v & x->mark.m;
int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
family = x->props.family;
@@ -1067,7 +1074,7 @@ int xfrm_state_add(struct xfrm_state *x)
}
if (use_spi && x->km.seq) {
- x1 = __xfrm_find_acq_byseq(net, x->km.seq);
+ x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq);
if (x1 && ((x1->id.proto != x->id.proto) ||
xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) {
to_put = x1;
@@ -1076,8 +1083,8 @@ int xfrm_state_add(struct xfrm_state *x)
}
if (use_spi && !x1)
- x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid,
- x->id.proto,
+ x1 = __find_acq_core(net, &x->mark, family, x->props.mode,
+ x->props.reqid, x->id.proto,
&x->id.daddr, &x->props.saddr, 0);
__xfrm_state_bump_genids(x);
@@ -1151,6 +1158,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
goto error;
}
+ memcpy(&x->mark, &orig->mark, sizeof(x->mark));
+
err = xfrm_init_state(x);
if (err)
goto error;
@@ -1342,41 +1351,41 @@ int xfrm_state_check_expire(struct xfrm_state *x)
EXPORT_SYMBOL(xfrm_state_check_expire);
struct xfrm_state *
-xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto,
- unsigned short family)
+xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi,
+ u8 proto, unsigned short family)
{
struct xfrm_state *x;
spin_lock_bh(&xfrm_state_lock);
- x = __xfrm_state_lookup(net, daddr, spi, proto, family);
+ x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
spin_unlock_bh(&xfrm_state_lock);
return x;
}
EXPORT_SYMBOL(xfrm_state_lookup);
struct xfrm_state *
-xfrm_state_lookup_byaddr(struct net *net,
+xfrm_state_lookup_byaddr(struct net *net, u32 mark,
xfrm_address_t *daddr, xfrm_address_t *saddr,
u8 proto, unsigned short family)
{
struct xfrm_state *x;
spin_lock_bh(&xfrm_state_lock);
- x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family);
+ x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
spin_unlock_bh(&xfrm_state_lock);
return x;
}
EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
struct xfrm_state *
-xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto,
+xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto,
xfrm_address_t *daddr, xfrm_address_t *saddr,
int create, unsigned short family)
{
struct xfrm_state *x;
spin_lock_bh(&xfrm_state_lock);
- x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create);
+ x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
spin_unlock_bh(&xfrm_state_lock);
return x;
@@ -1423,7 +1432,7 @@ EXPORT_SYMBOL(xfrm_state_sort);
/* Silly enough, but I'm lazy to build resolution list */
-static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
+static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
{
int i;
@@ -1442,12 +1451,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
return NULL;
}
-struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq)
+struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
{
struct xfrm_state *x;
spin_lock_bh(&xfrm_state_lock);
- x = __xfrm_find_acq_byseq(net, seq);
+ x = __xfrm_find_acq_byseq(net, mark, seq);
spin_unlock_bh(&xfrm_state_lock);
return x;
}
@@ -1474,6 +1483,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
int err = -ENOENT;
__be32 minspi = htonl(low);
__be32 maxspi = htonl(high);
+ u32 mark = x->mark.v & x->mark.m;
spin_lock_bh(&x->lock);
if (x->km.state == XFRM_STATE_DEAD)
@@ -1486,7 +1496,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
err = -ENOENT;
if (minspi == maxspi) {
- x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family);
+ x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
if (x0) {
xfrm_state_put(x0);
goto unlock;
@@ -1496,7 +1506,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
u32 spi = 0;
for (h=0; h<high-low+1; h++) {
spi = low + net_random()%(high-low+1);
- x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
+ x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
if (x0 == NULL) {
x->id.spi = htonl(spi);
break;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ee04e6b..331ae73 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -31,6 +31,9 @@
#include <linux/in6.h>
#endif
+#define DUMMY_MARK 0
+static struct xfrm_mark dummy_mark = {0, 0};
+
static inline int aead_len(struct xfrm_algo_aead *alg)
{
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -530,7 +533,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
err = -ESRCH;
- x = xfrm_state_lookup(net, &p->daddr, p->spi, p->proto, p->family);
+ x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family);
} else {
xfrm_address_t *saddr = NULL;
@@ -541,7 +544,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
}
err = -ESRCH;
- x = xfrm_state_lookup_byaddr(net, &p->daddr, saddr,
+ x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr,
p->proto, p->family);
}
@@ -958,7 +961,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
x = NULL;
if (p->info.seq) {
- x = xfrm_find_acq_byseq(net, p->info.seq);
+ x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq);
if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
xfrm_state_put(x);
x = NULL;
@@ -966,7 +969,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
}
if (!x)
- x = xfrm_find_acq(net, p->info.mode, p->info.reqid,
+ x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid,
p->info.id.proto, daddr,
&p->info.saddr, 1,
family);
@@ -1598,7 +1601,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (r_skb == NULL)
return -ENOMEM;
- x = xfrm_state_lookup(net, &id->daddr, id->spi, id->proto, id->family);
+ x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family);
if (x == NULL) {
kfree_skb(r_skb);
return -ESRCH;
@@ -1640,7 +1643,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
return err;
- x = xfrm_state_lookup(net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
+ x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
if (x == NULL)
return -ESRCH;
@@ -1767,7 +1770,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_user_expire *ue = nlmsg_data(nlh);
struct xfrm_usersa_info *p = &ue->state;
- x = xfrm_state_lookup(net, &p->id.daddr, p->id.spi, p->id.proto, p->family);
+ x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family);
err = -ENOENT;
if (x == NULL)
--
1.6.0.4
^ permalink raw reply related
* [net-next-2.6 PATCH 1/7] xfrm: introduce basic mark infrastructure
From: jamal @ 2010-02-22 21:32 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <1266874380-29593-1-git-send-email-hadi@cyberus.ca>
From: Jamal Hadi Salim <hadi@cyberus.ca>
Add basic structuring and accessors for xfrm mark
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
include/linux/xfrm.h | 12 +++++++++---
include/net/xfrm.h | 22 ++++++++++++++++++++++
2 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 29e04be..b971e38 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -267,8 +267,8 @@ enum xfrm_attr_type_t {
XFRMA_ALG_COMP, /* struct xfrm_algo */
XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */
XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */
- XFRMA_SA,
- XFRMA_POLICY,
+ XFRMA_SA, /* struct xfrm_usersa_info */
+ XFRMA_POLICY, /*struct xfrm_userpolicy_info */
XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */
XFRMA_LTIME_VAL,
XFRMA_REPLAY_VAL,
@@ -276,17 +276,23 @@ enum xfrm_attr_type_t {
XFRMA_ETIMER_THRESH,
XFRMA_SRCADDR, /* xfrm_address_t */
XFRMA_COADDR, /* xfrm_address_t */
- XFRMA_LASTUSED,
+ XFRMA_LASTUSED, /* unsigned long */
XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */
XFRMA_MIGRATE,
XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */
XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */
XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */
+ XFRMA_MARK, /* struct xfrm_mark */
__XFRMA_MAX
#define XFRMA_MAX (__XFRMA_MAX - 1)
};
+struct xfrm_mark {
+ __u32 v; /* value */
+ __u32 m; /* mask */
+};
+
enum xfrm_sadattr_type_t {
XFRMA_SAD_UNSPEC,
XFRMA_SAD_CNT,
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0beb413..39f151c 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -140,6 +140,7 @@ struct xfrm_state {
struct xfrm_id id;
struct xfrm_selector sel;
+ struct xfrm_mark mark;
u32 genid;
@@ -481,6 +482,7 @@ struct xfrm_policy {
u32 priority;
u32 index;
+ struct xfrm_mark mark;
struct xfrm_selector selector;
struct xfrm_lifetime_cfg lft;
struct xfrm_lifetime_cur curlft;
@@ -1570,4 +1572,24 @@ static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
}
#endif
+static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
+{
+ if (attrs[XFRMA_MARK])
+ memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(m));
+ else
+ m->v = m->m = 0;
+
+ return m->v & m->m;
+}
+
+static inline int xfrm_mark_put(struct sk_buff *skb, struct xfrm_mark *m)
+{
+ if (m->m | m->v)
+ NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m);
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
#endif /* _NET_XFRM_H */
--
1.6.0.4
^ permalink raw reply related
* [net-next-2.6 PATCH 0/7] xfrm by MARK
From: jamal @ 2010-02-22 21:32 UTC (permalink / raw)
To: davem; +Cc: timo.teras, kaber, herbert, netdev, Jamal Hadi Salim
In-Reply-To: <xfrm-mark-v3>
From: Jamal Hadi Salim <hadi@cyberus.ca>
Changes since last time:
----------------------
Patch 1/7: Feedback from David Miller; aggregate xfrm_*mark
and correct comment on the type of xfrm_mark
Changes since first time:
----------------------
Patch 1/7: Feedback from Patrick McHardy; We pass to user space any
mark as long as it has non-zero mask.
This patchset implements manipulation of ipsec tables with the
"mark" tag. You can config the SAD and SPD from user space
with a specified mark.
Example:
---
#ip xfrm state add src 192.168.2.100 dst 192.168.1.10 proto esp spi 0x00000301 mode tunnel mark 7 auth md5 0x96358c90783bbfa3d7b196ceabe0536b enc des3_ede 0xf6ddb555acfd9d77b03ea3843f2653255afe8eb5573965df
#ip xfrm state get mark 7 src 192.168.2.100 dst 192.168.1.10 proto esp spi 0x00000301
output:
src 192.168.2.100 dst 192.168.1.10
proto esp spi 0x00000301 reqid 0 mode tunnel
replay-window 0
mark 7/0xffffffff
auth hmac(md5) 0x96358c90783bbfa3d7b196ceabe0536b
enc cbc(des3_ede) 0xf6ddb555acfd9d77b03ea3843f2653255afe8eb5573965df
sel src 0.0.0.0/0 dst 0.0.0.0/0
#
#
#ip xfrm policy add src 172.16.2.0/24 dst 172.16.1.0/24 \
dir fwd ptype main \
tmpl src 192.168.2.100 dst 192.168.1.100 \
proto esp mode tunnel mark 7 mask 0xffffffff
#
#ip xfrm policy ls
output:
src 172.16.2.0/24 dst 172.16.1.0/24
dir fwd priority 0 ptype main
mark 7/0xffffffff
tmpl src 192.168.2.100 dst 192.168.1.100
proto esp reqid 0 mode tunnel
-----
A mark-configured SAD/SPD entry will use the mark as part of the
lookup key (both in data and control path).
Example:
---
# ip xfrm pol get src 172.16.2.0/24 dst 172.16.1.0/24 dir fwd
output:
RTNETLINK answers: No such file or directory
# ip xfrm pol get src 172.16.2.0/24 dst 172.16.1.0/24 dir fwd mark 7
output:
src 172.16.2.0/24 dst 172.16.1.0/24
dir fwd priority 0 ptype main
mark 7/0xffffffff
tmpl src 192.168.2.100 dst 192.168.1.100
proto esp reqid 0 mode tunnel
---
Jamal Hadi Salim (7):
xfrm: introduce basic mark infrastructure
xfrm: SA lookups signature with mark
xfrm: SA lookups with mark
xfrm: SP lookups signature with mark
xfrm: SP lookups with mark
xfrm: Allow user space config of SAD mark
xfrm: Allow user space manipulation of SPD mark
include/linux/xfrm.h | 12 ++++-
include/net/xfrm.h | 50 ++++++++++++++++++++----
net/core/pktgen.c | 3 +-
net/ipv4/ah4.c | 2 +-
net/ipv4/esp4.c | 2 +-
net/ipv4/ipcomp.c | 6 ++-
net/ipv6/ah6.c | 2 +-
net/ipv6/esp6.c | 2 +-
net/ipv6/ipcomp6.c | 6 ++-
net/ipv6/xfrm6_input.c | 2 +-
net/key/af_key.c | 16 ++++---
net/xfrm/xfrm_input.c | 2 +-
net/xfrm/xfrm_policy.c | 20 +++++++--
net/xfrm/xfrm_state.c | 70 +++++++++++++++++++++++------------
net/xfrm/xfrm_user.c | 96 ++++++++++++++++++++++++++++++++++++++++--------
15 files changed, 216 insertions(+), 75 deletions(-)
^ permalink raw reply
* Re: [Bugme-new] [Bug 15342] New: max_address parameter is not taken into consideration when IPv6 addresses are created
From: Andrew Morton @ 2010-02-22 21:08 UTC (permalink / raw)
To: netdev; +Cc: bugzilla-daemon, bugme-daemon, nedyalkor
In-Reply-To: <bug-15342-10286@http.bugzilla.kernel.org/>
(switched to email. Please respond via emailed reply-to-all, not via the
bugzilla web interface).
On Wed, 17 Feb 2010 14:12:28 GMT bugzilla-daemon@bugzilla.kernel.org wrote:
> http://bugzilla.kernel.org/show_bug.cgi?id=15342
>
> Summary: max_address parameter is not taken into consideration
> when IPv6 addresses are created
> Product: Networking
> Version: 2.5
> Kernel Version: 2.6.32.5
> Platform: All
> OS/Version: Linux
> Tree: Mainline
> Status: NEW
> Severity: low
> Priority: P1
> Component: IPV6
> AssignedTo: yoshfuji@linux-ipv6.org
> ReportedBy: nedyalkor@gmail.com
> Regression: No
>
>
> >From ip-sysctl.txt file in kernel documentation I can see following description
> for max_addresses:
> max_addresses - INTEGER
> Number of maximum addresses per interface. 0 disables limitation.
> It is recommended not set too large value (or 0) because it would
> be too easy way to crash kernel to allow to create too much of
> autoconfigured addresses.
> Default: 16
>
> On my machine all parameters are set to default value 16:
> # sysctl -a|grep max_addresses
> net.ipv6.conf.all.max_addresses = 16
> net.ipv6.conf.default.max_addresses = 16
> net.ipv6.conf.lo.max_addresses = 16
> net.ipv6.conf.eth0.max_addresses = 16
>
> To my understanding I should not be able to create more than 16 IP addresses,
> but in fact I am able do it:
>
> # for i in `seq 1 16`; do ip addr add fec0::$i/64 dev eth0; done
> # ip addr add fec0::17/64 dev eth0
> # ip -6 addr
> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436
> inet6 ::1/128 scope host
> valid_lft forever preferred_lft forever
> 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
> inet6 fec0::17/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::16/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::15/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::14/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::13/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::12/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::11/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::10/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::9/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::8/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::7/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::6/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::5/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::4/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::3/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::2/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fec0::1/64 scope site
> valid_lft forever preferred_lft forever
> inet6 fe80::223:aeff:fe77:44ba/64 scope link
> valid_lft forever preferred_lft forever
>
>
> If this parameter applies only for auto-configured IP addressed, please state
> it more clearly in docs or rename the parameter to show that it refers to
> auto-configuration.
>
^ permalink raw reply
* [PATCH] isdn: fix a few Kconfig imperfections
From: Tilman Schmidt @ 2010-02-22 21:09 UTC (permalink / raw)
To: Karsten Keil
Cc: Karsten Keil, David Miller, isdn4linux, i4ldeveloper, netdev,
linux-kernel
1. Rewrite the outdated help texts for config options ISDN and ISDN_CAPI.
2. The MISDN config option appeared between ISDN_I4L and the I4L hardware
driver options; move it to a less irritating place.
3. HYSDN is not in fact an I4L driver, and needn't depend on ISDN_I4L, so
move it from the I4L section to the general section.
4. ISDN_HDLC is now also used by drivers outside I4L. Move it from the
I4L section to the general section, too.
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
---
drivers/isdn/Kconfig | 43 ++++++++++++++++++++++++++++---------------
drivers/isdn/i4l/Kconfig | 7 -------
2 files changed, 28 insertions(+), 22 deletions(-)
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 022a194..4fb6016 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -7,15 +7,14 @@ menuconfig ISDN
depends on NET
depends on !S390
---help---
- ISDN ("Integrated Services Digital Networks", called RNIS in France)
- is a special type of fully digital telephone service; it's mostly
- used to connect to your Internet service provider (with SLIP or
- PPP). The main advantage is that the speed is higher than ordinary
- modem/telephone connections, and that you can have voice
- conversations while downloading stuff. It only works if your
- computer is equipped with an ISDN card and both you and your service
- provider purchased an ISDN line from the phone company. For
- details, read <http://www.alumni.caltech.edu/~dank/isdn/> on the WWW.
+ ISDN ("Integrated Services Digital Network", called RNIS in France)
+ is a fully digital telephone service that can be used for voice and
+ data connections. If your computer is equipped with an ISDN
+ adapter you can use it to connect to your Internet service provider
+ (with SLIP or PPP) faster than via a conventional telephone modem
+ (though still much slower than with DSL) or to make and accept
+ voice calls (eg. turning your PC into a software answering machine
+ or PABX).
Select this option if you want your kernel to support ISDN.
@@ -39,17 +38,22 @@ menuconfig ISDN_I4L
It is still available, though, for use with adapters that are not
supported by the new CAPI subsystem yet.
-source "drivers/isdn/mISDN/Kconfig"
-
source "drivers/isdn/i4l/Kconfig"
menuconfig ISDN_CAPI
tristate "CAPI 2.0 subsystem"
help
- This provides the CAPI (Common ISDN Application Programming
- Interface, a standard making it easy for programs to access ISDN
- hardware, see <http://www.capi.org/>. This is needed for AVM's set
- of active ISDN controllers like B1, T1, M1.
+ This provides CAPI (the Common ISDN Application Programming
+ Interface) Version 2.0, a standard making it easy for programs to
+ access ISDN hardware in a device independent way. (For details see
+ <http://www.capi.org/>.) CAPI supports making and accepting voice
+ and data connections, controlling call options and protocols,
+ as well as ISDN supplementary services like call forwarding or
+ three-party conferences (if supported by the specific hardware
+ driver).
+
+ Select this option and the appropriate hardware driver below if
+ you have an ISDN adapter supported by the CAPI subsystem.
if ISDN_CAPI
@@ -61,4 +65,13 @@ endif # ISDN_CAPI
source "drivers/isdn/gigaset/Kconfig"
+source "drivers/isdn/hysdn/Kconfig"
+
+source "drivers/isdn/mISDN/Kconfig"
+
+config ISDN_HDLC
+ tristate
+ select CRC_CCITT
+ select BITREVERSE
+
endif # ISDN
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 07c4e49..9c6650e 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -134,14 +134,7 @@ source "drivers/isdn/sc/Kconfig"
source "drivers/isdn/act2000/Kconfig"
-source "drivers/isdn/hysdn/Kconfig"
-
endmenu
# end ISDN_I4L
endif
-config ISDN_HDLC
- tristate
- select CRC_CCITT
- select BITREVERSE
-
--
1.6.5.3.298.g39add
^ permalink raw reply related
* Re: [PATCH 3/5] Add checkpoint support for veth devices (v2)
From: Dan Smith @ 2010-02-22 21:01 UTC (permalink / raw)
To: Serge E. Hallyn; +Cc: containers, netdev
In-Reply-To: <20100222205738.GA18038@us.ibm.com>
SH> So do you actually know that the peer's netns will have been
SH> checkpointed? I'm a little fuzzy about where netns and netdevs
SH> are checkpointed. If you have two private netns's in a container,
SH> with a veth connecting them, and you checkpoint a task in netns 1,
SH> will you fail bc netns 2 hasn't been checkpointed yet bc no task
SH> in it has been checkpointed yet?
Nope, because they're collect()'ed before we checkpoint().
--
Dan Smith
IBM Linux Technology Center
email: danms@us.ibm.com
^ permalink raw reply
* Re: [PATCH 3/5] Add checkpoint support for veth devices (v2)
From: Serge E. Hallyn @ 2010-02-22 20:57 UTC (permalink / raw)
To: Dan Smith; +Cc: containers, netdev
In-Reply-To: <87sk8t6msb.fsf@caffeine.danplanet.com>
Quoting Dan Smith (danms@us.ibm.com):
> >> + else if (!ckpt_obj_lookup(ctx, peer->nd_net, CKPT_OBJ_NET_NS)) {
> >> + ret = -EINVAL;
> >> + ckpt_err(ctx, ret,
> >> + "Peer %s of %s not in checkpointed namespaces\n",
> >> + peer->name, dev->name);
>
> SH> I'm not sure this check does what you think it does: note that
> SH> ckpt_netdev_base(), defined in the previous patch, and called
> SH> higher up in this function, is going to checkpoint peer->nd_net.
> SH> :)
>
> Actually, no, ckpt_netdev_base() can't checkpoint peer->nd_net because
> it's device-agnostic and has no knowledge of dev->peer.
Oh, ok.
> The idea here was that we checkpoint a netns when we arrive at it via
> nsproxy. Doing that, we checkpoint the devices within. We encounter
> a veth device, which has a peer, so we decide if:
>
> 1. We won't arrive at the peer later because it is in the init
> namespace, so we checkpoint it now.
> 2. We will arrive at it later because the peer's netns is in the list
> we've already collected, so checkpoint the peer with its namespace
> 3. Neither are true and we won't arrive at it later and therefore we
> can't allow checkpoint to continue
>
> #2 depends on the collect process having put all the task's netns' in
> the hash ahead of time.
Right, that was what I was originally starting to hunt down when I
thought I saw ckpt_netdev_base() checkpointing peer's netns.
So do you actually know that the peer's netns will have been
checkpointed? I'm a little fuzzy about where netns and netdevs
are checkpointed. If you have two private netns's in a container,
with a veth connecting them, and you checkpoint a task in netns 1,
will you fail bc netns 2 hasn't been checkpointed yet bc no task in
it has been checkpointed yet?
-serge
^ permalink raw reply
* Re: RFC: netfilter: nf_conntrack: add support for "conntrack zones"
From: Eric W. Biederman @ 2010-02-22 20:46 UTC (permalink / raw)
To: hadi
Cc: Patrick McHardy, Linux Netdev List, containers,
Netfilter Development Mailinglist, Ben Greear
In-Reply-To: <1263568754.23480.142.camel@bigi>
jamal <hadi@cyberus.ca> writes:
>> > Agreed. But the major ones like iproute2 etc could be taught. We have
>> > namespaces in the kernel already, over a period of time I think changing
>> > the user space tools would a sensible evolution.
>>
>> Yes, that might be useful in any case. But I don't think it would
>> even work for iproute or other standalone programs, a process can't
>> associate to an existing namespace except through clone(). So it
>> needs to run as child of a process already associated with the
>> namespace.
>
> The mechanics are not there, yet. But if i had sufficient permission,
> and was able to find the namespaces when i ask and/or get events when it
> is created it should be an issue of sending it a message.
> The current approach to say migrate a veth via iproute2 requires we
> know the pid of the target namespace. Thats a usability issue.
> I tried to muck with namespaces and if you use a library like lxc
> you can do it - but it is a hack as it stands today (and merging
> iproute2 with lxc is questionable).
This is one of the long standing issues that we have always known
we needed to solve, but have not taken the time to do it. Now that
the need is more real it looks about time to solve this one.
There are currently two problems.
1) A process is needed to hold a reference to the network namespace.
2) We use pids which are an awkward way of talking about network
namespaces.
The solution I have been playing with involves.
- Using a file descriptor to refer to a network namespace.
- Using a trivial virtual filesystem to persistently hold onto
a namespace without the need of a process.
- Have a convention of mounting the fs at something like
/var/run/netns/<name>
That solves the naming problem, and it should allow iproute and
it's kin to have support without being closely integrated with
lxc or anything else that creates namespaces.
It is a big conversation, and it is something that has to done
right but it looks like the problem is finally real enough that
it is time to solve it.
Eric
^ permalink raw reply
* Re: [PATCH 3/5] Add checkpoint support for veth devices (v2)
From: Dan Smith @ 2010-02-22 20:25 UTC (permalink / raw)
To: Serge E. Hallyn; +Cc: containers, netdev
In-Reply-To: <20100222195647.GB13135@us.ibm.com>
>> + else if (!ckpt_obj_lookup(ctx, peer->nd_net, CKPT_OBJ_NET_NS)) {
>> + ret = -EINVAL;
>> + ckpt_err(ctx, ret,
>> + "Peer %s of %s not in checkpointed namespaces\n",
>> + peer->name, dev->name);
SH> I'm not sure this check does what you think it does: note that
SH> ckpt_netdev_base(), defined in the previous patch, and called
SH> higher up in this function, is going to checkpoint peer->nd_net.
SH> :)
Actually, no, ckpt_netdev_base() can't checkpoint peer->nd_net because
it's device-agnostic and has no knowledge of dev->peer.
The idea here was that we checkpoint a netns when we arrive at it via
nsproxy. Doing that, we checkpoint the devices within. We encounter
a veth device, which has a peer, so we decide if:
1. We won't arrive at the peer later because it is in the init
namespace, so we checkpoint it now.
2. We will arrive at it later because the peer's netns is in the list
we've already collected, so checkpoint the peer with its namespace
3. Neither are true and we won't arrive at it later and therefore we
can't allow checkpoint to continue
#2 depends on the collect process having put all the task's netns' in
the hash ahead of time.
--
Dan Smith
IBM Linux Technology Center
email: danms@us.ibm.com
^ permalink raw reply
* Re: [PATCH 3/5] Add checkpoint support for veth devices (v2)
From: Serge E. Hallyn @ 2010-02-22 19:56 UTC (permalink / raw)
To: Dan Smith
Cc: containers-qjLDD68F18O7TbgM5vRIOg, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1266336187-19105-4-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Quoting Dan Smith (danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org):
> Adds an ndo_checkpoint() handler for veth devices to checkpoint themselves.
> Writes out the pairing information, addresses, and initiates a checkpoint
> on the peer if the peer won't be reached from another netns. Throws an
> error of our peer's netns isn't already in the hash (i.e., a tree leak).
>
> Changes in v2:
> - Fix check detecting if peer is in the init netns
>
> Signed-off-by: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> ---
> drivers/net/veth.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 76 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/veth.c b/drivers/net/veth.c
> index 3a15de5..db92de8 100644
> --- a/drivers/net/veth.c
> +++ b/drivers/net/veth.c
> @@ -16,6 +16,9 @@
> #include <net/xfrm.h>
> #include <linux/veth.h>
>
> +#include <linux/checkpoint.h>
> +#include <linux/checkpoint_hdr.h>
> +
> #define DRV_NAME "veth"
> #define DRV_VERSION "1.0"
>
> @@ -284,6 +287,76 @@ static void veth_dev_free(struct net_device *dev)
> free_netdev(dev);
> }
>
> +#ifdef CONFIG_CHECKPOINT
> +static int veth_checkpoint(struct ckpt_ctx *ctx, struct net_device *dev)
> +{
> + struct ckpt_hdr_netdev *h;
> + struct veth_priv *priv = netdev_priv(dev);
> + struct net_device *peer = priv->peer;
> + struct ckpt_netdev_addr *addrs;
> + int ret;
> + int n;
> +
> + if (!peer) {
> + ckpt_err(ctx, -EINVAL, "veth device has no peer!\n");
> + return -EINVAL;
> + }
> +
> + h = ckpt_netdev_base(ctx, dev, &addrs);
> + if (IS_ERR(h))
> + return PTR_ERR(h);
> +
> + h->type = CKPT_NETDEV_VETH;
> +
> + ret = h->veth.this_ref = ckpt_obj_lookup_add(ctx, dev,
> + CKPT_OBJ_NETDEV, &n);
> + if (ret < 0)
> + goto out;
> +
> + ret = h->veth.peer_ref = ckpt_obj_lookup_add(ctx, peer,
> + CKPT_OBJ_NETDEV, &n);
> + if (ret < 0)
> + goto out;
> +
> + ret = ckpt_write_obj(ctx, (struct ckpt_hdr *)h);
> + if (ret < 0)
> + goto out;
> +
> + ret = ckpt_write_buffer(ctx, dev->name, IFNAMSIZ);
> + if (ret < 0)
> + goto out;
> +
> + ret = ckpt_write_buffer(ctx, peer->name, IFNAMSIZ);
> + if (ret < 0)
> + goto out;
> +
> + if (h->inet_addrs > 0) {
> + int len = (sizeof(struct ckpt_netdev_addr) * h->inet_addrs);
> + ret = ckpt_write_buffer(ctx, addrs, len);
> + if (ret)
> + goto out;
> + }
> +
> + /* Only checkpoint peer if we're not going to arrive at it
> + * via another task's netns. Fail if the pipe exits
> + * our container to a netns not already in the hash
> + */
> + if (ckpt_netdev_in_init_netns(ctx, peer))
> + ret = checkpoint_obj(ctx, peer, CKPT_OBJ_NETDEV);
> + else if (!ckpt_obj_lookup(ctx, peer->nd_net, CKPT_OBJ_NET_NS)) {
> + ret = -EINVAL;
> + ckpt_err(ctx, ret,
> + "Peer %s of %s not in checkpointed namespaces\n",
> + peer->name, dev->name);
I'm not sure this check does what you think it does: note that
ckpt_netdev_base(), defined in the previous patch, and called higher
up in this function, is going to checkpoint peer->nd_net. :)
(right?)
> + }
> + out:
> + ckpt_hdr_put(ctx, h);
> + kfree(addrs);
> +
> + return ret;
> +}
> +#endif
> +
> static const struct net_device_ops veth_netdev_ops = {
> .ndo_init = veth_dev_init,
> .ndo_open = veth_open,
> @@ -292,6 +365,9 @@ static const struct net_device_ops veth_netdev_ops = {
> .ndo_change_mtu = veth_change_mtu,
> .ndo_get_stats = veth_get_stats,
> .ndo_set_mac_address = eth_mac_addr,
> +#ifdef CONFIG_CHECKPOINT
> + .ndo_checkpoint = veth_checkpoint,
> +#endif
> };
>
> static void veth_setup(struct net_device *dev)
> --
> 1.6.2.5
>
> _______________________________________________
> Containers mailing list
> Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
> https://lists.linux-foundation.org/mailman/listinfo/containers
^ permalink raw reply
* [net-next-2.6 PATCH] net: convert multiple drivers to use netdev_for_each_mc_addr, part4
From: Jiri Pirko @ 2010-02-22 19:22 UTC (permalink / raw)
To: netdev; +Cc: davem
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
drivers/net/davinci_emac.c | 5 ++---
drivers/net/e100.c | 10 +++++++---
drivers/net/eepro.c | 8 +++-----
drivers/net/eexpress.c | 16 ++++++----------
drivers/net/ehea/ehea_main.c | 5 ++---
drivers/net/enic/enic_main.c | 10 ++++++----
drivers/net/epic100.c | 3 +--
drivers/net/ethoc.c | 6 +++---
drivers/net/ewrk3.c | 5 ++---
drivers/net/fealnx.c | 4 +---
drivers/net/fec.c | 6 ++----
drivers/net/fec_mpc52xx.c | 5 +----
drivers/net/forcedeth.c | 6 ++----
drivers/net/fs_enet/mac-fcc.c | 2 +-
drivers/net/fs_enet/mac-fec.c | 2 +-
drivers/net/fs_enet/mac-scc.c | 2 +-
drivers/net/gianfar.c | 2 +-
drivers/net/hamachi.c | 7 ++++---
drivers/net/hp100.c | 6 +++---
drivers/net/ibm_newemac/core.c | 2 +-
drivers/net/ibmlana.c | 2 +-
drivers/net/ibmveth.c | 5 ++---
drivers/net/igb/igb_main.c | 12 ++++--------
drivers/net/igbvf/netdev.c | 12 +++---------
drivers/net/ioc3-eth.c | 6 ++----
drivers/net/ipg.c | 3 +--
drivers/net/isa-skeleton.c | 2 +-
drivers/net/iseries_veth.c | 6 ++----
drivers/net/ixgb/ixgb_main.c | 7 +++----
29 files changed, 69 insertions(+), 98 deletions(-)
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index d1e03b5..3f5db83 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -965,10 +965,9 @@ static void emac_dev_mcast_set(struct net_device *ndev)
mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL);
/* program multicast address list into EMAC hardware */
- for (mc_ptr = ndev->mc_list; mc_ptr;
- mc_ptr = mc_ptr->next) {
+ netdev_for_each_mc_addr(mc_ptr, ndev) {
emac_add_mcast(priv, EMAC_MULTICAST_ADD,
- (u8 *)mc_ptr->dmi_addr);
+ (u8 *) mc_ptr->dmi_addr);
}
} else {
mbp_enable = (mbp_enable & ~EMAC_MBP_RXMCAST);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index e8c0e82..a26ccab 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1537,14 +1537,18 @@ static int e100_hw_init(struct nic *nic)
static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
struct net_device *netdev = nic->netdev;
- struct dev_mc_list *list = netdev->mc_list;
+ struct dev_mc_list *list;
u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS);
cb->command = cpu_to_le16(cb_multi);
cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
- for (i = 0; list && i < count; i++, list = list->next)
- memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr,
+ i = 0;
+ netdev_for_each_mc_addr(list, netdev) {
+ if (i == count)
+ break;
+ memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &list->dmi_addr,
ETH_ALEN);
+ }
}
static void e100_set_multicast_list(struct net_device *netdev)
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 5f73ab2..1b05bdf 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -1287,7 +1287,7 @@ set_multicast_list(struct net_device *dev)
struct eepro_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
unsigned short mode;
- struct dev_mc_list *dmi=dev->mc_list;
+ struct dev_mc_list *dmi;
int mc_count = netdev_mc_count(dev);
if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63)
@@ -1332,10 +1332,8 @@ set_multicast_list(struct net_device *dev)
outw(0, ioaddr + IO_PORT);
outw(6 * (mc_count + 1), ioaddr + IO_PORT);
- for (i = 0; i < mc_count; i++)
- {
- eaddrs=(unsigned short *)dmi->dmi_addr;
- dmi=dmi->next;
+ netdev_for_each_mc_addr(dmi, dev) {
+ eaddrs = (unsigned short *) dmi->dmi_addr;
outw(*eaddrs++, ioaddr + IO_PORT);
outw(*eaddrs++, ioaddr + IO_PORT);
outw(*eaddrs++, ioaddr + IO_PORT);
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index d804ff1..7013dc8 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -1588,23 +1588,19 @@ static void eexp_setup_filter(struct net_device *dev)
outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR);
outw(6*count, ioaddr+SHADOW(CONF_NR_MULTICAST));
- for (i = 0, dmi = dev->mc_list; i < count; i++, dmi = dmi->next) {
- unsigned short *data;
- if (!dmi) {
- printk(KERN_INFO "%s: too few multicast addresses\n", dev->name);
+ i = 0;
+ netdev_for_each_mc_addr(dmi, dev) {
+ unsigned short *data = (unsigned short *) dmi->dmi_addr;
+
+ if (i == count)
break;
- }
- if (dmi->dmi_addrlen != ETH_ALEN) {
- printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);
- continue;
- }
- data = (unsigned short *)dmi->dmi_addr;
outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR);
outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i)));
outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR);
outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2));
outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR);
outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4));
+ i++;
}
}
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 99e4f83..b004eab 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -1967,7 +1967,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
{
struct ehea_port *port = netdev_priv(dev);
struct dev_mc_list *k_mcl_entry;
- int ret, i;
+ int ret;
if (dev->flags & IFF_PROMISC) {
ehea_promiscuous(dev, 1);
@@ -1997,8 +1997,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
goto out;
}
- for (i = 0, k_mcl_entry = dev->mc_list; i < netdev_mc_count(dev); i++,
- k_mcl_entry = k_mcl_entry->next)
+ netdev_for_each_mc_addr(k_mcl_entry, dev)
ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr);
}
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 94749eb..cf098bb 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -822,7 +822,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr)
static void enic_set_multicast_list(struct net_device *netdev)
{
struct enic *enic = netdev_priv(netdev);
- struct dev_mc_list *list = netdev->mc_list;
+ struct dev_mc_list *list;
int directed = 1;
int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0;
int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0;
@@ -851,9 +851,11 @@ static void enic_set_multicast_list(struct net_device *netdev)
* look for changes to add/del.
*/
- for (i = 0; list && i < mc_count; i++) {
- memcpy(mc_addr[i], list->dmi_addr, ETH_ALEN);
- list = list->next;
+ i = 0;
+ netdev_for_each_mc_addr(list, netdev) {
+ if (i == mc_count)
+ break;
+ memcpy(mc_addr[i++], list->dmi_addr, ETH_ALEN);
}
for (i = 0; i < enic->mc_count; i++) {
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 31a3adb..39c271b 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1403,8 +1403,7 @@ static void set_rx_mode(struct net_device *dev)
struct dev_mc_list *mclist;
memset(mc_filter, 0, sizeof(mc_filter));
- for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev);
- i++, mclist = mclist->next) {
+ netdev_for_each_mc_addr(mclist, dev) {
unsigned int bit_nr =
ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f;
mc_filter[bit_nr >> 3] |= (1 << bit_nr);
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index f9d5ca0..2097423 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -755,7 +755,7 @@ static void ethoc_set_multicast_list(struct net_device *dev)
{
struct ethoc *priv = netdev_priv(dev);
u32 mode = ethoc_read(priv, MODER);
- struct dev_mc_list *mc = NULL;
+ struct dev_mc_list *mc;
u32 hash[2] = { 0, 0 };
/* set loopback mode if requested */
@@ -783,8 +783,8 @@ static void ethoc_set_multicast_list(struct net_device *dev)
hash[0] = 0xffffffff;
hash[1] = 0xffffffff;
} else {
- for (mc = dev->mc_list; mc; mc = mc->next) {
- u32 crc = ether_crc(mc->dmi_addrlen, mc->dmi_addr);
+ netdev_for_each_mc_addr(mc, dev) {
+ u32 crc = ether_crc(ETH_ALEN, mc->dmi_addr);
int bit = (crc >> 26) & 0x3f;
hash[bit >> 5] |= 1 << (bit & 0x1f);
}
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 96817a8..91e59f3 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -1169,7 +1169,7 @@ static void set_multicast_list(struct net_device *dev)
static void SetMulticastFilter(struct net_device *dev)
{
struct ewrk3_private *lp = netdev_priv(dev);
- struct dev_mc_list *dmi = dev->mc_list;
+ struct dev_mc_list *dmi;
u_long iobase = dev->base_addr;
int i;
char *addrs, bit, byte;
@@ -1213,9 +1213,8 @@ static void SetMulticastFilter(struct net_device *dev)
}
/* Update table */
- for (i = 0; i < netdev_mc_count(dev); i++) { /* for each address in the list */
+ netdev_for_each_mc_addr(dmi, dev) {
addrs = dmi->dmi_addr;
- dmi = dmi->next;
if ((*addrs & 0x01) == 1) { /* multicast address? */
crc = ether_crc_le(ETH_ALEN, addrs);
hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index f95b5ff..9d5ad08 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1793,11 +1793,9 @@ static void __set_rx_mode(struct net_device *dev)
rx_mode = CR_W_AB | CR_W_AM;
} else {
struct dev_mc_list *mclist;
- int i;
memset(mc_filter, 0, sizeof(mc_filter));
- for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev);
- i++, mclist = mclist->next) {
+ netdev_for_each_mc_addr(mclist, dev) {
unsigned int bit;
bit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F;
mc_filter[bit >> 5] |= (1 << bit);
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index d9d14c8..9f98c1c 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1575,7 +1575,7 @@ static void set_multicast_list(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
struct dev_mc_list *dmi;
- unsigned int i, j, bit, data, crc, tmp;
+ unsigned int i, bit, data, crc, tmp;
unsigned char hash;
if (dev->flags & IFF_PROMISC) {
@@ -1604,9 +1604,7 @@ static void set_multicast_list(struct net_device *dev)
writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
- dmi = dev->mc_list;
-
- for (j = 0; j < netdev_mc_count(dev); j++, dmi = dmi->next) {
+ netdev_for_each_mc_addr(dmi, dev) {
/* Only support group multicast for now */
if (!(dmi->dmi_addr[0] & 1))
continue;
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 10903b7..0dbd721 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -575,19 +575,16 @@ static void mpc52xx_fec_set_multicast_list(struct net_device *dev)
out_be32(&fec->gaddr2, 0xffffffff);
} else {
u32 crc;
- int i;
struct dev_mc_list *dmi;
u32 gaddr1 = 0x00000000;
u32 gaddr2 = 0x00000000;
- dmi = dev->mc_list;
- for (i=0; i<netdev_mc_count(dev); i++) {
+ netdev_for_each_mc_addr(dmi, dev) {
crc = ether_crc_le(6, dmi->dmi_addr) >> 26;
if (crc >= 32)
gaddr1 |= 1 << (crc-32);
else
gaddr2 |= 1 << crc;
- dmi = dmi->next;
}
out_be32(&fec->gaddr1, gaddr1);
out_be32(&fec->gaddr2, gaddr2);
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 3eb713b..ca05e56 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -3095,7 +3095,7 @@ static void nv_set_multicast(struct net_device *dev)
} else {
pff |= NVREG_PFF_MYADDR;
- if (dev->flags & IFF_ALLMULTI || dev->mc_list) {
+ if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) {
u32 alwaysOff[2];
u32 alwaysOn[2];
@@ -3105,8 +3105,7 @@ static void nv_set_multicast(struct net_device *dev)
} else {
struct dev_mc_list *walk;
- walk = dev->mc_list;
- while (walk != NULL) {
+ netdev_for_each_mc_addr(walk, dev) {
u32 a, b;
a = le32_to_cpu(*(__le32 *) walk->dmi_addr);
b = le16_to_cpu(*(__le16 *) (&walk->dmi_addr[4]));
@@ -3114,7 +3113,6 @@ static void nv_set_multicast(struct net_device *dev)
alwaysOff[0] &= ~a;
alwaysOn[1] &= b;
alwaysOff[1] &= ~b;
- walk = walk->next;
}
}
addr[0] = alwaysOn[0];
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 482f27d..a761d31 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -235,7 +235,7 @@ static void set_multicast_list(struct net_device *dev)
if ((dev->flags & IFF_PROMISC) == 0) {
set_multicast_start(dev);
- for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+ netdev_for_each_mc_addr(pmc, dev)
set_multicast_one(dev, pmc->dmi_addr);
set_multicast_finish(dev);
} else
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index ddf13ef..ca806d1 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -236,7 +236,7 @@ static void set_multicast_list(struct net_device *dev)
if ((dev->flags & IFF_PROMISC) == 0) {
set_multicast_start(dev);
- for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+ netdev_for_each_mc_addr(pmc, dev)
set_multicast_one(dev, pmc->dmi_addr);
set_multicast_finish(dev);
} else
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 141dbc9..5bfc99b 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -228,7 +228,7 @@ static void set_multicast_list(struct net_device *dev)
if ((dev->flags & IFF_PROMISC) == 0) {
set_multicast_start(dev);
- for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+ netdev_for_each_mc_addr(pmc, dev)
set_multicast_one(dev, pmc->dmi_addr);
set_multicast_finish(dev);
} else
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index c9be090..6aa526e 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -2867,7 +2867,7 @@ static void gfar_set_multi(struct net_device *dev)
return;
/* Parse the list, and set the appropriate bits */
- for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+ netdev_for_each_mc_addr(mc_ptr, dev) {
if (idx < em_num) {
gfar_set_mac_for_addr(dev, idx,
mc_ptr->dmi_addr);
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index c70b147..373546d 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1859,12 +1859,13 @@ static void set_rx_mode(struct net_device *dev)
writew(0x000B, ioaddr + AddrMode);
} else if (!netdev_mc_empty(dev)) { /* Must use the CAM filter. */
struct dev_mc_list *mclist;
- int i;
- for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev);
- i++, mclist = mclist->next) {
+ int i = 0;
+
+ netdev_for_each_mc_addr(mclist, dev) {
writel(*(u32*)(mclist->dmi_addr), ioaddr + 0x100 + i*8);
writel(0x20000 | (*(u16*)&mclist->dmi_addr[4]),
ioaddr + 0x104 + i*8);
+ i++;
}
/* Clear remaining entries. */
for (; i < 64; i++)
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index debac1b..b766a69 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2098,7 +2098,7 @@ static void hp100_set_multicast_list(struct net_device *dev)
/* set hash filter to receive all multicast packets */
memset(&lp->hash_bytes, 0xff, 8);
} else {
- int i, j, idx;
+ int i, idx;
u_char *addrs;
struct dev_mc_list *dmi;
@@ -2107,14 +2107,14 @@ static void hp100_set_multicast_list(struct net_device *dev)
printk("hp100: %s: computing hash filter - mc_count = %i\n",
dev->name, netdev_mc_count(dev));
#endif
- for (i = 0, dmi = dev->mc_list; i < netdev_mc_count(dev); i++, dmi = dmi->next) {
+ netdev_for_each_mc_addr(dmi, dev) {
addrs = dmi->dmi_addr;
if ((*addrs & 0x01) == 0x01) { /* multicast address? */
#ifdef HP100_DEBUG
printk("hp100: %s: multicast = %pM, ",
dev->name, addrs);
#endif
- for (j = idx = 0; j < 6; j++) {
+ for (i = idx = 0; i < 6; i++) {
idx ^= *addrs++ & 0x3f;
printk(":%02x:", idx);
}
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index b75d27e..fb0ac6d 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -395,7 +395,7 @@ static void emac_hash_mc(struct emac_instance *dev)
memset(gaht_temp, 0, sizeof (gaht_temp));
- for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
+ netdev_for_each_mc_addr(dmi, dev->ndev) {
int slot, reg, mask;
DBG2(dev, "mc %pM" NL, dmi->dmi_addr);
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 052c740..b5d0f4e 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -420,7 +420,7 @@ static void InitBoard(struct net_device *dev)
/* start putting the multicast addresses into the CAM list. Stop if
it is full. */
- for (mcptr = dev->mc_list; mcptr != NULL; mcptr = mcptr->next) {
+ netdev_for_each_mc_addr(mcptr, dev) {
putcam(cams, &camcnt, mcptr->dmi_addr);
if (camcnt == 16)
break;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 41b9c0e..f2b9379 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1072,8 +1072,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
}
} else {
- struct dev_mc_list *mclist = netdev->mc_list;
- int i;
+ struct dev_mc_list *mclist;
/* clear the filter table & disable filtering */
lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
IbmVethMcastEnableRecv |
@@ -1084,7 +1083,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
}
/* add the addresses to the filter table */
- for(i = 0; i < netdev_mc_count(netdev); ++i, mclist = mclist->next) {
+ netdev_for_each_mc_addr(mclist, netdev) {
// add the multicast address to the filter table
unsigned long mcast_addr = 0;
memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index f588e49..583a21c 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -2877,7 +2877,7 @@ static int igb_write_mc_addr_list(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- struct dev_mc_list *mc_ptr = netdev->mc_list;
+ struct dev_mc_list *mc_ptr;
u8 *mta_list;
int i;
@@ -2893,14 +2893,10 @@ static int igb_write_mc_addr_list(struct net_device *netdev)
return -ENOMEM;
/* The shared function expects a packed array of only addresses. */
- mc_ptr = netdev->mc_list;
+ i = 0;
+ netdev_for_each_mc_addr(mc_ptr, netdev)
+ memcpy(mta_list + (i++ * ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
- for (i = 0; i < netdev_mc_count(netdev); i++) {
- if (!mc_ptr)
- break;
- memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
- mc_ptr = mc_ptr->next;
- }
igb_update_mc_addr_list(hw, mta_list, i);
kfree(mta_list);
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 6029c40..a77afd8 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -1413,15 +1413,9 @@ static void igbvf_set_multi(struct net_device *netdev)
}
/* prepare a packed array of only addresses. */
- mc_ptr = netdev->mc_list;
-
- for (i = 0; i < netdev_mc_count(netdev); i++) {
- if (!mc_ptr)
- break;
- memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr,
- ETH_ALEN);
- mc_ptr = mc_ptr->next;
- }
+ i = 0;
+ netdev_for_each_mc_addr(mc_ptr, netdev)
+ memcpy(mta_list + (i++ * ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 0, 0);
kfree(mta_list);
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 0bd5fef..70871b9 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -1664,11 +1664,10 @@ static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static void ioc3_set_multicast_list(struct net_device *dev)
{
- struct dev_mc_list *dmi = dev->mc_list;
+ struct dev_mc_list *dmi;
struct ioc3_private *ip = netdev_priv(dev);
struct ioc3 *ioc3 = ip->regs;
u64 ehar = 0;
- int i;
netif_stop_queue(dev); /* Lock out others. */
@@ -1689,9 +1688,8 @@ static void ioc3_set_multicast_list(struct net_device *dev)
ip->ehar_h = 0xffffffff;
ip->ehar_l = 0xffffffff;
} else {
- for (i = 0; i < netdev_mc_count(dev); i++) {
+ netdev_for_each_mc_addr(dmi, dev) {
char *addr = dmi->dmi_addr;
- dmi = dmi->next;
if (!(*addr & 1))
continue;
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 3ca49e3..150415e 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -608,8 +608,7 @@ static void ipg_nic_set_multicast_list(struct net_device *dev)
hashtable[1] = 0x00000000;
/* Cycle through all multicast addresses to filter. */
- for (mc_list_ptr = dev->mc_list;
- mc_list_ptr != NULL; mc_list_ptr = mc_list_ptr->next) {
+ netdev_for_each_mc_addr(mc_list_ptr, dev) {
/* Calculate CRC result for each multicast address. */
hashindex = crc32_le(0xffffffff, mc_list_ptr->dmi_addr,
ETH_ALEN);
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
index bb4a3cd..d09e4d3 100644
--- a/drivers/net/isa-skeleton.c
+++ b/drivers/net/isa-skeleton.c
@@ -666,7 +666,7 @@ set_multicast_list(struct net_device *dev)
else if (!netdev_mc_empty(dev))
{
/* Walk the address list, and load the filter */
- hardware_set_filter(dev->mc_list);
+ hardware_set_filter(dev);
outw(MULTICAST, ioaddr);
}
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index ff015e1..966de5d 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -961,15 +961,14 @@ static void veth_set_multicast_list(struct net_device *dev)
(netdev_mc_count(dev) > VETH_MAX_MCAST)) {
port->promiscuous = 1;
} else {
- struct dev_mc_list *dmi = dev->mc_list;
- int i;
+ struct dev_mc_list *dmi;
port->promiscuous = 0;
/* Update table */
port->num_mcast = 0;
- for (i = 0; i < netdev_mc_count(dev); i++) {
+ netdev_for_each_mc_addr(dmi, dev) {
u8 *addr = dmi->dmi_addr;
u64 xaddr = 0;
@@ -978,7 +977,6 @@ static void veth_set_multicast_list(struct net_device *dev)
port->mcast_addr[port->num_mcast] = xaddr;
port->num_mcast++;
}
- dmi = dmi->next;
}
}
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 93d0185..c9fef65 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1088,10 +1088,9 @@ ixgb_set_multi(struct net_device *netdev)
IXGB_WRITE_REG(hw, RCTL, rctl);
- for (i = 0, mc_ptr = netdev->mc_list;
- mc_ptr;
- i++, mc_ptr = mc_ptr->next)
- memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS],
+ i = 0;
+ netdev_for_each_mc_addr(mc_ptr, netdev)
+ memcpy(&mta[i++ * IXGB_ETH_LENGTH_OF_ADDRESS],
mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
ixgb_mc_addr_list_update(hw, mta, netdev_mc_count(netdev), 0);
--
1.6.6
^ permalink raw reply related
* [PATCH 2/5] temac: dma init for Virtex4
From: gfilip @ 2010-02-22 19:06 UTC (permalink / raw)
To: netdev; +Cc: glikely, Filip Gospodinov
In-Reply-To: <1266865621-28955-1-git-send-email-gfilip@ee.ethz.ch>
This patch belongs to a set of patches which extends the temac driver to support Virtex4-FX. It was successfully tested on the ML403 evaluation board.
Signed-off-by: Filip Gospodinov <gfilip@ee.ethz.ch>
---
drivers/net/ll_temac.h | 4 ++++
drivers/net/ll_temac_main.c | 17 ++++++++++++++++-
2 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h
index 95dd650..51824a8 100644
--- a/drivers/net/ll_temac.h
+++ b/drivers/net/ll_temac.h
@@ -383,7 +383,11 @@ struct temac_local {
/* IO registers and IRQs */
void __iomem *regs;
+#ifdef CONFIG_XILINX_VIRTEX_4_FX
+ void __iomem *dma_regs;
+#else
dcr_host_t sdma_dcrs;
+#endif
int tx_irq;
int rx_irq;
int emac_num;
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index a8522bd..0d4b1c5 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -812,7 +812,6 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
struct net_device *ndev;
const void *addr;
int size, rc = 0;
- unsigned int dcrs;
/* Init network device structure */
ndev = alloc_etherdev(sizeof(*lp));
@@ -862,6 +861,21 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
goto nodev;
}
+#ifdef CONFIG_XILINX_VIRTEX_4_FX
+ unsigned int ds;
+ const u32 *dr = of_get_property(np, "reg", &ds);
+ if (dr == NULL || ds & 1 || 0 >= ds ) {
+ dev_err(&op->dev, "could not get DMA register address\n");
+ goto nodev;
+ }
+ lp->dma_regs = (u32) ioremap(*dr, 4096);
+ if (!lp->dma_regs) {
+ dev_err(&op->dev, "could not get DMA virtual address\n");
+ goto nodev;
+ }
+ dev_dbg(&op->dev, "DMA base: %x\n", lp->dma_regs);
+#else /*CONFIG_XILINX_VIRTEX_4_FX*/
+ unsigned int dcrs;
dcrs = dcr_resource_start(np, 0);
if (dcrs == 0) {
dev_err(&op->dev, "could not get DMA register address\n");
@@ -869,6 +883,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
}
lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
+#endif /*CONFIG_XILINX_VIRTEX_4_FX*/'
lp->rx_irq = irq_of_parse_and_map(np, 0);
lp->tx_irq = irq_of_parse_and_map(np, 1);
--
1.6.4.4
^ permalink raw reply related
* [PATCH 4/5] temac: dma MMIO for Virtex4
From: gfilip @ 2010-02-22 19:07 UTC (permalink / raw)
To: netdev; +Cc: glikely, Filip Gospodinov
In-Reply-To: <1266865621-28955-3-git-send-email-gfilip@ee.ethz.ch>
This patch belongs to a set of patches which extends the temac driver to support Virtex4-FX. It was successfully tested on the ML403 evaluation board.
Signed-off-by: Filip Gospodinov <gfilip@ee.ethz.ch>
---
drivers/net/ll_temac_main.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index 2e7421c..8b4e1b9 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -115,6 +115,17 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
}
+#ifdef CONFIG_XILINX_VIRTEX_4_FX
+static u32 temac_dma_in32(struct temac_local *lp, int reg)
+{
+ return in_be32((u32 *)(lp->dma_regs + reg));
+}
+
+static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
+{
+ out_be32((u32 *)(lp->dma_regs + reg), value);
+}
+#else
static u32 temac_dma_in32(struct temac_local *lp, int reg)
{
return dcr_read(lp->sdma_dcrs, reg);
@@ -124,6 +135,7 @@ static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
{
dcr_write(lp->sdma_dcrs, reg, value);
}
+#endif
/**
* temac_dma_bd_init - Setup buffer descriptor rings
--
1.6.4.4
^ permalink raw reply related
* [PATCH 1/5] temac: Add Virtex4 address mappings
From: gfilip @ 2010-02-22 19:06 UTC (permalink / raw)
To: netdev; +Cc: glikely, Filip Gospodinov
This patch belongs to a set of patches which extends the temac driver to support Virtex4-FX. It was successfully tested on the ML403 evaluation board.
Signed-off-by: Filip Gospodinov <gfilip@ee.ethz.ch>
---
drivers/net/ll_temac.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h
index 1af66a1..95dd650 100644
--- a/drivers/net/ll_temac.h
+++ b/drivers/net/ll_temac.h
@@ -56,7 +56,52 @@ This option defaults to enabled (set) */
XTE_OPTION_RXEN)
/* XPS_LL_TEMAC SDMA registers definition */
+#ifdef CONFIG_XILINX_VIRTEX_4_FX
+#define TX_NXTDESC_PTR 0x00 /* r */
+#define TX_CURBUF_ADDR 0x04 /* r */
+#define TX_CURBUF_LENGTH 0x08 /* r */
+#define TX_CURDESC_PTR 0x0C /* rw */
+#define TX_TAILDESC_PTR 0x10 /* rw */
+#define TX_CHNL_CTRL 0x14 /* rw */
+#define CHNL_CTRL_IRQ_IOE (1 << 9)
+#define CHNL_CTRL_IRQ_EN (1 << 7)
+#define CHNL_CTRL_IRQ_ERR_EN (1 << 2)
+#define CHNL_CTRL_IRQ_DLY_EN (1 << 1)
+#define CHNL_CTRL_IRQ_COAL_EN (1 << 0)
+#define TX_IRQ_REG 0x18 /* rw */
+#define TX_CHNL_STS 0x1C /* r */
+#define RX_NXTDESC_PTR 0x20 /* r */
+#define RX_CURBUF_ADDR 0x24 /* r */
+#define RX_CURBUF_LENGTH 0x28 /* r */
+#define RX_CURDESC_PTR 0x2C /* rw */
+#define RX_TAILDESC_PTR 0x30 /* rw */
+#define RX_CHNL_CTRL 0x34 /* rw */
+#define RX_IRQ_REG 0x38 /* rw */
+#define IRQ_COAL (1 << 0)
+#define IRQ_DLY (1 << 1)
+#define IRQ_ERR (1 << 2)
+#define IRQ_DMAERR (1 << 7) /* this is not documented ??? */
+#define RX_CHNL_STS 0x3C /* r */
+#define CHNL_STS_ENGBUSY (1 << 1)
+#define CHNL_STS_EOP (1 << 2)
+#define CHNL_STS_SOP (1 << 3)
+#define CHNL_STS_CMPLT (1 << 4)
+#define CHNL_STS_SOE (1 << 5)
+#define CHNL_STS_IOE (1 << 6)
+#define CHNL_STS_ERR (1 << 7)
+
+#define CHNL_STS_BSYWR (1 << 16)
+#define CHNL_STS_CURPERR (1 << 17)
+#define CHNL_STS_NXTPERR (1 << 18)
+#define CHNL_STS_ADDRERR (1 << 19)
+#define CHNL_STS_CMPERR (1 << 20)
+#define CHNL_STS_TAILERR (1 << 21)
+
+#define DMA_CONTROL_REG 0x40 /* rw */
+#define DMA_CONTROL_RST (1 << 0)
+#define DMA_TAIL_ENABLE (1 << 2)
+#else
#define TX_NXTDESC_PTR 0x00 /* r */
#define TX_CURBUF_ADDR 0x01 /* r */
#define TX_CURBUF_LENGTH 0x02 /* r */
@@ -182,6 +227,7 @@ This option defaults to enabled (set) */
#define DMA_CONTROL_REG 0x10 /* rw */
#define DMA_CONTROL_RST (1 << 0)
#define DMA_TAIL_ENABLE (1 << 2)
+#endif /*CONFIG_XILINX_VIRTEX_4_FX*/
/* XPS_LL_TEMAC direct registers definition */
--
1.6.4.4
^ permalink raw reply related
* [PATCH 3/5] temac: dma deinit
From: gfilip @ 2010-02-22 19:06 UTC (permalink / raw)
To: netdev; +Cc: glikely, Filip Gospodinov
In-Reply-To: <1266865621-28955-2-git-send-email-gfilip@ee.ethz.ch>
This patch belongs to a set of patches which extends the temac driver to support Virtex4-FX. It was successfully tested on the ML403 evaluation board.
Signed-off-by: Filip Gospodinov <gfilip@ee.ethz.ch>
---
drivers/net/ll_temac_main.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index 0d4b1c5..2e7421c 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -946,6 +946,9 @@ static int __devexit temac_of_remove(struct of_device *op)
if (lp->phy_node)
of_node_put(lp->phy_node);
lp->phy_node = NULL;
+#ifdef CONFIG_XILINX_VIRTEX_4_FX
+ iounmap((void *) lp->dma_regs);
+#endif
dev_set_drvdata(&op->dev, NULL);
free_netdev(ndev);
return 0;
--
1.6.4.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox