Initial commit: Linux kernel 4.19 for Unplugged OS

This commit is contained in:
ziv committed 2025-10-06 13:52:42 +00:00
commit d30235b04c
80519 files changed
+35800681

No files matched your search

+330
View File
@@ -0,0 +1,330 @@
/*
* Copyright 2011, Siemens AG
* written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
/*
* Based on patches from Jon Smirl <jonsmirl@gmail.com>
* Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Jon's code is based on 6lowpan implementation for Contiki which is:
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __6LOWPAN_H__
#define __6LOWPAN_H__
#include <linux/debugfs.h>
#include <net/ipv6.h>
#include <net/net_namespace.h>
/* special link-layer handling */
#include <net/mac802154.h>
#define EUI64_ADDR_LEN 8
#define LOWPAN_NHC_MAX_ID_LEN 1
/* Maximum next header compression length which we currently support inclusive
* possible inline data.
*/
#define LOWPAN_NHC_MAX_HDR_LEN (sizeof(struct udphdr))
/* Max IPHC Header len without IPv6 hdr specific inline data.
* Useful for getting the "extra" bytes we need at worst case compression.
*
* LOWPAN_IPHC + CID + LOWPAN_NHC_MAX_ID_LEN
*/
#define LOWPAN_IPHC_MAX_HEADER_LEN (2 + 1 + LOWPAN_NHC_MAX_ID_LEN)
/* Maximum worst case IPHC header buffer size */
#define LOWPAN_IPHC_MAX_HC_BUF_LEN (sizeof(struct ipv6hdr) + \
LOWPAN_IPHC_MAX_HEADER_LEN + \
LOWPAN_NHC_MAX_HDR_LEN)
/* SCI/DCI is 4 bit width, so we have maximum 16 entries */
#define LOWPAN_IPHC_CTX_TABLE_SIZE (1 << 4)
#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
#define LOWPAN_DISPATCH_IPHC_MASK 0xe0
static inline bool lowpan_is_ipv6(u8 dispatch)
{
return dispatch == LOWPAN_DISPATCH_IPV6;
}
static inline bool lowpan_is_iphc(u8 dispatch)
{
return (dispatch & LOWPAN_DISPATCH_IPHC_MASK) == LOWPAN_DISPATCH_IPHC;
}
#define LOWPAN_PRIV_SIZE(llpriv_size) \
(sizeof(struct lowpan_dev) + llpriv_size)
enum lowpan_lltypes {
LOWPAN_LLTYPE_BTLE,
LOWPAN_LLTYPE_IEEE802154,
};
enum lowpan_iphc_ctx_flags {
LOWPAN_IPHC_CTX_FLAG_ACTIVE,
LOWPAN_IPHC_CTX_FLAG_COMPRESSION,
};
struct lowpan_iphc_ctx {
u8 id;
struct in6_addr pfx;
u8 plen;
unsigned long flags;
};
struct lowpan_iphc_ctx_table {
spinlock_t lock;
const struct lowpan_iphc_ctx_ops *ops;
struct lowpan_iphc_ctx table[LOWPAN_IPHC_CTX_TABLE_SIZE];
};
static inline bool lowpan_iphc_ctx_is_active(const struct lowpan_iphc_ctx *ctx)
{
return test_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &ctx->flags);
}
static inline bool
lowpan_iphc_ctx_is_compression(const struct lowpan_iphc_ctx *ctx)
{
return test_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags);
}
struct lowpan_dev {
enum lowpan_lltypes lltype;
struct dentry *iface_debugfs;
struct lowpan_iphc_ctx_table ctx;
/* must be last */
u8 priv[0] __aligned(sizeof(void *));
};
struct lowpan_802154_neigh {
__le16 short_addr;
};
static inline
struct lowpan_802154_neigh *lowpan_802154_neigh(void *neigh_priv)
{
return neigh_priv;
}
static inline
struct lowpan_dev *lowpan_dev(const struct net_device *dev)
{
return netdev_priv(dev);
}
/* private device info */
struct lowpan_802154_dev {
struct net_device *wdev; /* wpan device ptr */
u16 fragment_tag;
};
static inline struct
lowpan_802154_dev *lowpan_802154_dev(const struct net_device *dev)
{
return (struct lowpan_802154_dev *)lowpan_dev(dev)->priv;
}
struct lowpan_802154_cb {
u16 d_tag;
unsigned int d_size;
u8 d_offset;
};
static inline
struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct lowpan_802154_cb) > sizeof(skb->cb));
return (struct lowpan_802154_cb *)skb->cb;
}
static inline void lowpan_iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr,
const void *lladdr)
{
/* fe:80::XXXX:XXXX:XXXX:XXXX
* \_________________/
* hwaddr
*/
ipaddr->s6_addr[0] = 0xFE;
ipaddr->s6_addr[1] = 0x80;
memcpy(&ipaddr->s6_addr[8], lladdr, EUI64_ADDR_LEN);
/* second bit-flip (Universe/Local)
* is done according RFC2464
*/
ipaddr->s6_addr[8] ^= 0x02;
}
static inline void lowpan_iphc_uncompress_eui48_lladdr(struct in6_addr *ipaddr,
const void *lladdr)
{
/* fe:80::XXXX:XXff:feXX:XXXX
* \_________________/
* hwaddr
*/
ipaddr->s6_addr[0] = 0xFE;
ipaddr->s6_addr[1] = 0x80;
memcpy(&ipaddr->s6_addr[8], lladdr, 3);
ipaddr->s6_addr[11] = 0xFF;
ipaddr->s6_addr[12] = 0xFE;
memcpy(&ipaddr->s6_addr[13], lladdr + 3, 3);
}
#ifdef DEBUG
/* print data in line */
static inline void raw_dump_inline(const char *caller, char *msg,
const unsigned char *buf, int len)
{
if (msg)
pr_debug("%s():%s: ", caller, msg);
print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, false);
}
/* print data in a table format:
*
* addr: xx xx xx xx xx xx
* addr: xx xx xx xx xx xx
* ...
*/
static inline void raw_dump_table(const char *caller, char *msg,
const unsigned char *buf, int len)
{
if (msg)
pr_debug("%s():%s:\n", caller, msg);
print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 16, 1, buf, len, false);
}
#else
static inline void raw_dump_table(const char *caller, char *msg,
const unsigned char *buf, int len) { }
static inline void raw_dump_inline(const char *caller, char *msg,
const unsigned char *buf, int len) { }
#endif
/**
* lowpan_fetch_skb - getting inline data from 6LoWPAN header
*
* This function will pull data from sk buffer and put it into data to
* remove the 6LoWPAN inline data. This function returns true if the
* sk buffer is too small to pull the amount of data which is specified
* by len.
*
* @skb: the buffer where the inline data should be pulled from.
* @data: destination buffer for the inline data.
* @len: amount of data which should be pulled in bytes.
*/
static inline bool lowpan_fetch_skb(struct sk_buff *skb, void *data,
unsigned int len)
{
if (unlikely(!pskb_may_pull(skb, len)))
return true;
skb_copy_from_linear_data(skb, data, len);
skb_pull(skb, len);
return false;
}
static inline bool lowpan_802154_is_valid_src_short_addr(__le16 addr)
{
/* First bit of addr is multicast, reserved or 802.15.4 specific */
return !(addr & cpu_to_le16(0x8000));
}
static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
const size_t len)
{
memcpy(*hc_ptr, data, len);
*hc_ptr += len;
}
int lowpan_register_netdevice(struct net_device *dev,
enum lowpan_lltypes lltype);
int lowpan_register_netdev(struct net_device *dev,
enum lowpan_lltypes lltype);
void lowpan_unregister_netdevice(struct net_device *dev);
void lowpan_unregister_netdev(struct net_device *dev);
/**
* lowpan_header_decompress - replace 6LoWPAN header with IPv6 header
*
* This function replaces the IPHC 6LoWPAN header which should be pointed at
* skb->data and skb_network_header, with the IPv6 header.
* It would be nice that the caller have the necessary headroom of IPv6 header
* and greatest Transport layer header, this would reduce the overhead for
* reallocate headroom.
*
* @skb: the buffer which should be manipulate.
* @dev: the lowpan net device pointer.
* @daddr: destination lladdr of mac header which is used for compression
* methods.
* @saddr: source lladdr of mac header which is used for compression
* methods.
*/
int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
const void *daddr, const void *saddr);
/**
* lowpan_header_compress - replace IPv6 header with 6LoWPAN header
*
* This function replaces the IPv6 header which should be pointed at
* skb->data and skb_network_header, with the IPHC 6LoWPAN header.
* The caller need to be sure that the sk buffer is not shared and at have
* at least a headroom which is smaller or equal LOWPAN_IPHC_MAX_HEADER_LEN,
* which is the IPHC "more bytes than IPv6 header" at worst case.
*
* @skb: the buffer which should be manipulate.
* @dev: the lowpan net device pointer.
* @daddr: destination lladdr of mac header which is used for compression
* methods.
* @saddr: source lladdr of mac header which is used for compression
* methods.
*/
int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
const void *daddr, const void *saddr);
#endif /* __6LOWPAN_H__ */
+581
View File
@@ -0,0 +1,581 @@
/*
* include/net/9p/9p.h
*
* 9P protocol definitions.
*
* Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* Free Software Foundation
* 51 Franklin Street, Fifth Floor
* Boston, MA 02111-1301 USA
*
*/
#ifndef NET_9P_H
#define NET_9P_H
/**
* enum p9_debug_flags - bits for mount time debug parameter
* @P9_DEBUG_ERROR: more verbose error messages including original error string
* @P9_DEBUG_9P: 9P protocol tracing
* @P9_DEBUG_VFS: VFS API tracing
* @P9_DEBUG_CONV: protocol conversion tracing
* @P9_DEBUG_MUX: trace management of concurrent transactions
* @P9_DEBUG_TRANS: transport tracing
* @P9_DEBUG_SLABS: memory management tracing
* @P9_DEBUG_FCALL: verbose dump of protocol messages
* @P9_DEBUG_FID: fid allocation/deallocation tracking
* @P9_DEBUG_PKT: packet marshalling/unmarshalling
* @P9_DEBUG_FSC: FS-cache tracing
* @P9_DEBUG_VPKT: Verbose packet debugging (full packet dump)
*
* These flags are passed at mount time to turn on various levels of
* verbosity and tracing which will be output to the system logs.
*/
enum p9_debug_flags {
P9_DEBUG_ERROR = (1<<0),
P9_DEBUG_9P = (1<<2),
P9_DEBUG_VFS = (1<<3),
P9_DEBUG_CONV = (1<<4),
P9_DEBUG_MUX = (1<<5),
P9_DEBUG_TRANS = (1<<6),
P9_DEBUG_SLABS = (1<<7),
P9_DEBUG_FCALL = (1<<8),
P9_DEBUG_FID = (1<<9),
P9_DEBUG_PKT = (1<<10),
P9_DEBUG_FSC = (1<<11),
P9_DEBUG_VPKT = (1<<12),
};
#ifdef CONFIG_NET_9P_DEBUG
extern unsigned int p9_debug_level;
__printf(3, 4)
void _p9_debug(enum p9_debug_flags level, const char *func,
const char *fmt, ...);
#define p9_debug(level, fmt, ...) \
_p9_debug(level, __func__, fmt, ##__VA_ARGS__)
#else
#define p9_debug(level, fmt, ...) \
no_printk(fmt, ##__VA_ARGS__)
#endif
/**
* enum p9_msg_t - 9P message types
* @P9_TLERROR: not used
* @P9_RLERROR: response for any failed request for 9P2000.L
* @P9_TSTATFS: file system status request
* @P9_RSTATFS: file system status response
* @P9_TSYMLINK: make symlink request
* @P9_RSYMLINK: make symlink response
* @P9_TMKNOD: create a special file object request
* @P9_RMKNOD: create a special file object response
* @P9_TLCREATE: prepare a handle for I/O on an new file for 9P2000.L
* @P9_RLCREATE: response with file access information for 9P2000.L
* @P9_TRENAME: rename request
* @P9_RRENAME: rename response
* @P9_TMKDIR: create a directory request
* @P9_RMKDIR: create a directory response
* @P9_TVERSION: version handshake request
* @P9_RVERSION: version handshake response
* @P9_TAUTH: request to establish authentication channel
* @P9_RAUTH: response with authentication information
* @P9_TATTACH: establish user access to file service
* @P9_RATTACH: response with top level handle to file hierarchy
* @P9_TERROR: not used
* @P9_RERROR: response for any failed request
* @P9_TFLUSH: request to abort a previous request
* @P9_RFLUSH: response when previous request has been cancelled
* @P9_TWALK: descend a directory hierarchy
* @P9_RWALK: response with new handle for position within hierarchy
* @P9_TOPEN: prepare a handle for I/O on an existing file
* @P9_ROPEN: response with file access information
* @P9_TCREATE: prepare a handle for I/O on a new file
* @P9_RCREATE: response with file access information
* @P9_TREAD: request to transfer data from a file or directory
* @P9_RREAD: response with data requested
* @P9_TWRITE: reuqest to transfer data to a file
* @P9_RWRITE: response with out much data was transferred to file
* @P9_TCLUNK: forget about a handle to an entity within the file system
* @P9_RCLUNK: response when server has forgotten about the handle
* @P9_TREMOVE: request to remove an entity from the hierarchy
* @P9_RREMOVE: response when server has removed the entity
* @P9_TSTAT: request file entity attributes
* @P9_RSTAT: response with file entity attributes
* @P9_TWSTAT: request to update file entity attributes
* @P9_RWSTAT: response when file entity attributes are updated
*
* There are 14 basic operations in 9P2000, paired as
* requests and responses. The one special case is ERROR
* as there is no @P9_TERROR request for clients to transmit to
* the server, but the server may respond to any other request
* with an @P9_RERROR.
*
* See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html
*/
enum p9_msg_t {
P9_TLERROR = 6,
P9_RLERROR,
P9_TSTATFS = 8,
P9_RSTATFS,
P9_TLOPEN = 12,
P9_RLOPEN,
P9_TLCREATE = 14,
P9_RLCREATE,
P9_TSYMLINK = 16,
P9_RSYMLINK,
P9_TMKNOD = 18,
P9_RMKNOD,
P9_TRENAME = 20,
P9_RRENAME,
P9_TREADLINK = 22,
P9_RREADLINK,
P9_TGETATTR = 24,
P9_RGETATTR,
P9_TSETATTR = 26,
P9_RSETATTR,
P9_TXATTRWALK = 30,
P9_RXATTRWALK,
P9_TXATTRCREATE = 32,
P9_RXATTRCREATE,
P9_TREADDIR = 40,
P9_RREADDIR,
P9_TFSYNC = 50,
P9_RFSYNC,
P9_TLOCK = 52,
P9_RLOCK,
P9_TGETLOCK = 54,
P9_RGETLOCK,
P9_TLINK = 70,
P9_RLINK,
P9_TMKDIR = 72,
P9_RMKDIR,
P9_TRENAMEAT = 74,
P9_RRENAMEAT,
P9_TUNLINKAT = 76,
P9_RUNLINKAT,
P9_TVERSION = 100,
P9_RVERSION,
P9_TAUTH = 102,
P9_RAUTH,
P9_TATTACH = 104,
P9_RATTACH,
P9_TERROR = 106,
P9_RERROR,
P9_TFLUSH = 108,
P9_RFLUSH,
P9_TWALK = 110,
P9_RWALK,
P9_TOPEN = 112,
P9_ROPEN,
P9_TCREATE = 114,
P9_RCREATE,
P9_TREAD = 116,
P9_RREAD,
P9_TWRITE = 118,
P9_RWRITE,
P9_TCLUNK = 120,
P9_RCLUNK,
P9_TREMOVE = 122,
P9_RREMOVE,
P9_TSTAT = 124,
P9_RSTAT,
P9_TWSTAT = 126,
P9_RWSTAT,
};
/**
* enum p9_open_mode_t - 9P open modes
* @P9_OREAD: open file for reading only
* @P9_OWRITE: open file for writing only
* @P9_ORDWR: open file for reading or writing
* @P9_OEXEC: open file for execution
* @P9_OTRUNC: truncate file to zero-length before opening it
* @P9_OREXEC: close the file when an exec(2) system call is made
* @P9_ORCLOSE: remove the file when the file is closed
* @P9_OAPPEND: open the file and seek to the end
* @P9_OEXCL: only create a file, do not open it
*
* 9P open modes differ slightly from Posix standard modes.
* In particular, there are extra modes which specify different
* semantic behaviors than may be available on standard Posix
* systems. For example, @P9_OREXEC and @P9_ORCLOSE are modes that
* most likely will not be issued from the Linux VFS client, but may
* be supported by servers.
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/open
*/
enum p9_open_mode_t {
P9_OREAD = 0x00,
P9_OWRITE = 0x01,
P9_ORDWR = 0x02,
P9_OEXEC = 0x03,
P9_OTRUNC = 0x10,
P9_OREXEC = 0x20,
P9_ORCLOSE = 0x40,
P9_OAPPEND = 0x80,
P9_OEXCL = 0x1000,
};
/**
* enum p9_perm_t - 9P permissions
* @P9_DMDIR: mode bit for directories
* @P9_DMAPPEND: mode bit for is append-only
* @P9_DMEXCL: mode bit for excluse use (only one open handle allowed)
* @P9_DMMOUNT: mode bit for mount points
* @P9_DMAUTH: mode bit for authentication file
* @P9_DMTMP: mode bit for non-backed-up files
* @P9_DMSYMLINK: mode bit for symbolic links (9P2000.u)
* @P9_DMLINK: mode bit for hard-link (9P2000.u)
* @P9_DMDEVICE: mode bit for device files (9P2000.u)
* @P9_DMNAMEDPIPE: mode bit for named pipe (9P2000.u)
* @P9_DMSOCKET: mode bit for socket (9P2000.u)
* @P9_DMSETUID: mode bit for setuid (9P2000.u)
* @P9_DMSETGID: mode bit for setgid (9P2000.u)
* @P9_DMSETVTX: mode bit for sticky bit (9P2000.u)
*
* 9P permissions differ slightly from Posix standard modes.
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
*/
enum p9_perm_t {
P9_DMDIR = 0x80000000,
P9_DMAPPEND = 0x40000000,
P9_DMEXCL = 0x20000000,
P9_DMMOUNT = 0x10000000,
P9_DMAUTH = 0x08000000,
P9_DMTMP = 0x04000000,
/* 9P2000.u extensions */
P9_DMSYMLINK = 0x02000000,
P9_DMLINK = 0x01000000,
P9_DMDEVICE = 0x00800000,
P9_DMNAMEDPIPE = 0x00200000,
P9_DMSOCKET = 0x00100000,
P9_DMSETUID = 0x00080000,
P9_DMSETGID = 0x00040000,
P9_DMSETVTX = 0x00010000,
};
/* 9p2000.L open flags */
#define P9_DOTL_RDONLY 00000000
#define P9_DOTL_WRONLY 00000001
#define P9_DOTL_RDWR 00000002
#define P9_DOTL_NOACCESS 00000003
#define P9_DOTL_CREATE 00000100
#define P9_DOTL_EXCL 00000200
#define P9_DOTL_NOCTTY 00000400
#define P9_DOTL_TRUNC 00001000
#define P9_DOTL_APPEND 00002000
#define P9_DOTL_NONBLOCK 00004000
#define P9_DOTL_DSYNC 00010000
#define P9_DOTL_FASYNC 00020000
#define P9_DOTL_DIRECT 00040000
#define P9_DOTL_LARGEFILE 00100000
#define P9_DOTL_DIRECTORY 00200000
#define P9_DOTL_NOFOLLOW 00400000
#define P9_DOTL_NOATIME 01000000
#define P9_DOTL_CLOEXEC 02000000
#define P9_DOTL_SYNC 04000000
/* 9p2000.L at flags */
#define P9_DOTL_AT_REMOVEDIR 0x200
/* 9p2000.L lock type */
#define P9_LOCK_TYPE_RDLCK 0
#define P9_LOCK_TYPE_WRLCK 1
#define P9_LOCK_TYPE_UNLCK 2
/**
* enum p9_qid_t - QID types
* @P9_QTDIR: directory
* @P9_QTAPPEND: append-only
* @P9_QTEXCL: excluse use (only one open handle allowed)
* @P9_QTMOUNT: mount points
* @P9_QTAUTH: authentication file
* @P9_QTTMP: non-backed-up files
* @P9_QTSYMLINK: symbolic links (9P2000.u)
* @P9_QTLINK: hard-link (9P2000.u)
* @P9_QTFILE: normal files
*
* QID types are a subset of permissions - they are primarily
* used to differentiate semantics for a file system entity via
* a jump-table. Their value is also the most significant 16 bits
* of the permission_t
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
*/
enum p9_qid_t {
P9_QTDIR = 0x80,
P9_QTAPPEND = 0x40,
P9_QTEXCL = 0x20,
P9_QTMOUNT = 0x10,
P9_QTAUTH = 0x08,
P9_QTTMP = 0x04,
P9_QTSYMLINK = 0x02,
P9_QTLINK = 0x01,
P9_QTFILE = 0x00,
};
/* 9P Magic Numbers */
#define P9_NOTAG (u16)(~0)
#define P9_NOFID (u32)(~0)
#define P9_MAXWELEM 16
/* Minimal header size: size[4] type[1] tag[2] */
#define P9_HDRSZ 7
/* ample room for Twrite/Rread header */
#define P9_IOHDRSZ 24
/* Room for readdir header */
#define P9_READDIRHDRSZ 24
/* size of header for zero copy read/write */
#define P9_ZC_HDR_SZ 4096
/**
* struct p9_qid - file system entity information
* @type: 8-bit type &p9_qid_t
* @version: 16-bit monotonically incrementing version number
* @path: 64-bit per-server-unique ID for a file system element
*
* qids are identifiers used by 9P servers to track file system
* entities. The type is used to differentiate semantics for operations
* on the entity (ie. read means something different on a directory than
* on a file). The path provides a server unique index for an entity
* (roughly analogous to an inode number), while the version is updated
* every time a file is modified and can be used to maintain cache
* coherency between clients and serves.
* Servers will often differentiate purely synthetic entities by setting
* their version to 0, signaling that they should never be cached and
* should be accessed synchronously.
*
* See Also://plan9.bell-labs.com/magic/man2html/2/stat
*/
struct p9_qid {
u8 type;
u32 version;
u64 path;
};
/**
* struct p9_wstat - file system metadata information
* @size: length prefix for this stat structure instance
* @type: the type of the server (equivalent to a major number)
* @dev: the sub-type of the server (equivalent to a minor number)
* @qid: unique id from the server of type &p9_qid
* @mode: Plan 9 format permissions of type &p9_perm_t
* @atime: Last access/read time
* @mtime: Last modify/write time
* @length: file length
* @name: last element of path (aka filename)
* @uid: owner name
* @gid: group owner
* @muid: last modifier
* @extension: area used to encode extended UNIX support
* @n_uid: numeric user id of owner (part of 9p2000.u extension)
* @n_gid: numeric group id (part of 9p2000.u extension)
* @n_muid: numeric user id of laster modifier (part of 9p2000.u extension)
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
*/
struct p9_wstat {
u16 size;
u16 type;
u32 dev;
struct p9_qid qid;
u32 mode;
u32 atime;
u32 mtime;
u64 length;
const char *name;
const char *uid;
const char *gid;
const char *muid;
char *extension; /* 9p2000.u extensions */
kuid_t n_uid; /* 9p2000.u extensions */
kgid_t n_gid; /* 9p2000.u extensions */
kuid_t n_muid; /* 9p2000.u extensions */
};
struct p9_stat_dotl {
u64 st_result_mask;
struct p9_qid qid;
u32 st_mode;
kuid_t st_uid;
kgid_t st_gid;
u64 st_nlink;
u64 st_rdev;
u64 st_size;
u64 st_blksize;
u64 st_blocks;
u64 st_atime_sec;
u64 st_atime_nsec;
u64 st_mtime_sec;
u64 st_mtime_nsec;
u64 st_ctime_sec;
u64 st_ctime_nsec;
u64 st_btime_sec;
u64 st_btime_nsec;
u64 st_gen;
u64 st_data_version;
};
#define P9_STATS_MODE 0x00000001ULL
#define P9_STATS_NLINK 0x00000002ULL
#define P9_STATS_UID 0x00000004ULL
#define P9_STATS_GID 0x00000008ULL
#define P9_STATS_RDEV 0x00000010ULL
#define P9_STATS_ATIME 0x00000020ULL
#define P9_STATS_MTIME 0x00000040ULL
#define P9_STATS_CTIME 0x00000080ULL
#define P9_STATS_INO 0x00000100ULL
#define P9_STATS_SIZE 0x00000200ULL
#define P9_STATS_BLOCKS 0x00000400ULL
#define P9_STATS_BTIME 0x00000800ULL
#define P9_STATS_GEN 0x00001000ULL
#define P9_STATS_DATA_VERSION 0x00002000ULL
#define P9_STATS_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */
#define P9_STATS_ALL 0x00003fffULL /* Mask for All fields above */
/**
* struct p9_iattr_dotl - P9 inode attribute for setattr
* @valid: bitfield specifying which fields are valid
* same as in struct iattr
* @mode: File permission bits
* @uid: user id of owner
* @gid: group id
* @size: File size
* @atime_sec: Last access time, seconds
* @atime_nsec: Last access time, nanoseconds
* @mtime_sec: Last modification time, seconds
* @mtime_nsec: Last modification time, nanoseconds
*/
struct p9_iattr_dotl {
u32 valid;
u32 mode;
kuid_t uid;
kgid_t gid;
u64 size;
u64 atime_sec;
u64 atime_nsec;
u64 mtime_sec;
u64 mtime_nsec;
};
#define P9_LOCK_SUCCESS 0
#define P9_LOCK_BLOCKED 1
#define P9_LOCK_ERROR 2
#define P9_LOCK_GRACE 3
#define P9_LOCK_FLAGS_BLOCK 1
#define P9_LOCK_FLAGS_RECLAIM 2
/* struct p9_flock: POSIX lock structure
* @type - type of lock
* @flags - lock flags
* @start - starting offset of the lock
* @length - number of bytes
* @proc_id - process id which wants to take lock
* @client_id - client id
*/
struct p9_flock {
u8 type;
u32 flags;
u64 start;
u64 length;
u32 proc_id;
char *client_id;
};
/* struct p9_getlock: getlock structure
* @type - type of lock
* @start - starting offset of the lock
* @length - number of bytes
* @proc_id - process id which wants to take lock
* @client_id - client id
*/
struct p9_getlock {
u8 type;
u64 start;
u64 length;
u32 proc_id;
char *client_id;
};
struct p9_rstatfs {
u32 type;
u32 bsize;
u64 blocks;
u64 bfree;
u64 bavail;
u64 files;
u64 ffree;
u64 fsid;
u32 namelen;
};
/**
* struct p9_fcall - primary packet structure
* @size: prefixed length of the structure
* @id: protocol operating identifier of type &p9_msg_t
* @tag: transaction id of the request
* @offset: used by marshalling routines to track current position in buffer
* @capacity: used by marshalling routines to track total malloc'd capacity
* @sdata: payload
*
* &p9_fcall represents the structure for all 9P RPC
* transactions. Requests are packaged into fcalls, and reponses
* must be extracted from them.
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/fcall
*/
struct p9_fcall {
u32 size;
u8 id;
u16 tag;
size_t offset;
size_t capacity;
struct kmem_cache *cache;
u8 *sdata;
};
struct p9_idpool;
int p9_errstr2errno(char *errstr, int len);
struct p9_idpool *p9_idpool_create(void);
void p9_idpool_destroy(struct p9_idpool *);
int p9_idpool_get(struct p9_idpool *p);
void p9_idpool_put(int id, struct p9_idpool *p);
int p9_idpool_check(int id, struct p9_idpool *p);
int p9_error_init(void);
int p9_trans_fd_init(void);
void p9_trans_fd_exit(void);
#endif /* NET_9P_H */
+265
View File
@@ -0,0 +1,265 @@
/*
* include/net/9p/client.h
*
* 9P Client Definitions
*
* Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* Free Software Foundation
* 51 Franklin Street, Fifth Floor
* Boston, MA 02111-1301 USA
*
*/
#ifndef NET_9P_CLIENT_H
#define NET_9P_CLIENT_H
#include <linux/utsname.h>
#include <linux/idr.h>
/* Number of requests per row */
#define P9_ROW_MAXTAG 255
/** enum p9_proto_versions - 9P protocol versions
* @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
* @p9_proto_2000u: 9P2000.u extension
* @p9_proto_2000L: 9P2000.L extension
*/
enum p9_proto_versions{
p9_proto_legacy,
p9_proto_2000u,
p9_proto_2000L,
};
/**
* enum p9_trans_status - different states of underlying transports
* @Connected: transport is connected and healthy
* @Disconnected: transport has been disconnected
* @Hung: transport is connected by wedged
*
* This enumeration details the various states a transport
* instatiation can be in.
*/
enum p9_trans_status {
Connected,
BeginDisconnect,
Disconnected,
Hung,
};
/**
* enum p9_req_status_t - status of a request
* @REQ_STATUS_ALLOC: request has been allocated but not sent
* @REQ_STATUS_UNSENT: request waiting to be sent
* @REQ_STATUS_SENT: request sent to server
* @REQ_STATUS_RCVD: response received from server
* @REQ_STATUS_FLSHD: request has been flushed
* @REQ_STATUS_ERROR: request encountered an error on the client side
*/
enum p9_req_status_t {
REQ_STATUS_ALLOC,
REQ_STATUS_UNSENT,
REQ_STATUS_SENT,
REQ_STATUS_RCVD,
REQ_STATUS_FLSHD,
REQ_STATUS_ERROR,
};
/**
* struct p9_req_t - request slots
* @status: status of this request slot
* @t_err: transport error
* @wq: wait_queue for the client to block on for this request
* @tc: the request fcall structure
* @rc: the response fcall structure
* @aux: transport specific data (provided for trans_fd migration)
* @req_list: link for higher level objects to chain requests
*/
struct p9_req_t {
int status;
int t_err;
struct kref refcount;
wait_queue_head_t wq;
struct p9_fcall tc;
struct p9_fcall rc;
void *aux;
struct list_head req_list;
};
/**
* struct p9_client - per client instance state
* @lock: protect @fids and @reqs
* @msize: maximum data size negotiated by protocol
* @proto_version: 9P protocol version to use
* @trans_mod: module API instantiated with this client
* @status: connection state
* @trans: tranport instance state and API
* @fids: All active FID handles
* @reqs: All active requests.
* @name: node name used as client id
*
* The client structure is used to keep track of various per-client
* state that has been instantiated.
*/
struct p9_client {
spinlock_t lock;
unsigned int msize;
unsigned char proto_version;
struct p9_trans_module *trans_mod;
enum p9_trans_status status;
void *trans;
struct kmem_cache *fcall_cache;
union {
struct {
int rfd;
int wfd;
} fd;
struct {
u16 port;
bool privport;
} tcp;
} trans_opts;
struct idr fids;
struct idr reqs;
char name[__NEW_UTS_LEN + 1];
};
/**
* struct p9_fid - file system entity handle
* @clnt: back pointer to instantiating &p9_client
* @fid: numeric identifier for this handle
* @mode: current mode of this fid (enum?)
* @qid: the &p9_qid server identifier this handle points to
* @iounit: the server reported maximum transaction size for this file
* @uid: the numeric uid of the local user who owns this handle
* @rdir: readdir accounting structure (allocated on demand)
* @dlist: per-dentry fid tracking
*
* TODO: This needs lots of explanation.
*/
struct p9_fid {
struct p9_client *clnt;
u32 fid;
int mode;
struct p9_qid qid;
u32 iounit;
kuid_t uid;
void *rdir;
struct hlist_node dlist; /* list of all fids attached to a dentry */
};
/**
* struct p9_dirent - directory entry structure
* @qid: The p9 server qid for this dirent
* @d_off: offset to the next dirent
* @d_type: type of file
* @d_name: file name
*/
struct p9_dirent {
struct p9_qid qid;
u64 d_off;
unsigned char d_type;
char d_name[256];
};
struct iov_iter;
int p9_show_client_options(struct seq_file *m, struct p9_client *clnt);
int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
const char *name);
int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
struct p9_fid *newdirfid, const char *new_name);
struct p9_client *p9_client_create(const char *dev_name, char *options);
void p9_client_destroy(struct p9_client *clnt);
void p9_client_disconnect(struct p9_client *clnt);
void p9_client_begin_disconnect(struct p9_client *clnt);
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
const char *uname, kuid_t n_uname, const char *aname);
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
const unsigned char * const *wnames, int clone);
int p9_client_open(struct p9_fid *fid, int mode);
int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
char *extension);
int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, const char *newname);
int p9_client_symlink(struct p9_fid *fid, const char *name, const char *symname,
kgid_t gid, struct p9_qid *qid);
int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 mode,
kgid_t gid, struct p9_qid *qid);
int p9_client_clunk(struct p9_fid *fid);
int p9_client_fsync(struct p9_fid *fid, int datasync);
int p9_client_remove(struct p9_fid *fid);
int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err);
int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err);
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
int p9dirent_read(struct p9_client *clnt, char *buf, int len,
struct p9_dirent *dirent);
struct p9_wstat *p9_client_stat(struct p9_fid *fid);
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr);
struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
u64 request_mask);
int p9_client_mknod_dotl(struct p9_fid *oldfid, const char *name, int mode,
dev_t rdev, kgid_t gid, struct p9_qid *);
int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
kgid_t gid, struct p9_qid *);
int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
void p9_fcall_fini(struct p9_fcall *fc);
struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
static inline void p9_req_get(struct p9_req_t *r)
{
kref_get(&r->refcount);
}
static inline int p9_req_try_get(struct p9_req_t *r)
{
return kref_get_unless_zero(&r->refcount);
}
int p9_req_put(struct p9_req_t *r);
void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int);
int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *);
void p9stat_free(struct p9_wstat *);
int p9_is_proto_dotu(struct p9_client *clnt);
int p9_is_proto_dotl(struct p9_client *clnt);
struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *);
int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int);
int p9_client_readlink(struct p9_fid *fid, char **target);
int p9_client_init(void);
void p9_client_exit(void);
#endif /* NET_9P_CLIENT_H */
+73
View File
@@ -0,0 +1,73 @@
/*
* include/net/9p/transport.h
*
* Transport Definition
*
* Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* Free Software Foundation
* 51 Franklin Street, Fifth Floor
* Boston, MA 02111-1301 USA
*
*/
#ifndef NET_9P_TRANSPORT_H
#define NET_9P_TRANSPORT_H
#define P9_DEF_MIN_RESVPORT (665U)
#define P9_DEF_MAX_RESVPORT (1023U)
/**
* struct p9_trans_module - transport module interface
* @list: used to maintain a list of currently available transports
* @name: the human-readable name of the transport
* @maxsize: transport provided maximum packet size
* @def: set if this transport should be considered the default
* @create: member function to create a new connection on this transport
* @close: member function to discard a connection on this transport
* @request: member function to issue a request to the transport
* @cancel: member function to cancel a request (if it hasn't been sent)
* @cancelled: member function to notify that a cancelled request will not
* not receive a reply
*
* This is the basic API for a transport module which is registered by the
* transport module with the 9P core network module and used by the client
* to instantiate a new connection on a transport.
*
* The transport module list is protected by v9fs_trans_lock.
*/
struct p9_trans_module {
struct list_head list;
char *name; /* name of transport */
int maxsize; /* max message size of transport */
int def; /* this transport should be default */
struct module *owner;
int (*create)(struct p9_client *, const char *, char *);
void (*close) (struct p9_client *);
int (*request) (struct p9_client *, struct p9_req_t *req);
int (*cancel) (struct p9_client *, struct p9_req_t *req);
int (*cancelled)(struct p9_client *, struct p9_req_t *req);
int (*zc_request)(struct p9_client *, struct p9_req_t *,
struct iov_iter *, struct iov_iter *, int , int, int);
int (*show_options)(struct seq_file *, struct p9_client *);
};
void v9fs_register_trans(struct p9_trans_module *m);
void v9fs_unregister_trans(struct p9_trans_module *m);
struct p9_trans_module *v9fs_get_trans_by_name(char *s);
struct p9_trans_module *v9fs_get_default_trans(void);
void v9fs_put_trans(struct p9_trans_module *m);
#endif /* NET_9P_TRANSPORT_H */
+30
View File
@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* A unified ethernet device probe. This is the easiest way to have every
* ethernet adaptor have the name "eth[0123...]".
*/
struct net_device *hp100_probe(int unit);
struct net_device *ultra_probe(int unit);
struct net_device *wd_probe(int unit);
struct net_device *ne_probe(int unit);
struct net_device *fmv18x_probe(int unit);
struct net_device *i82596_probe(int unit);
struct net_device *ni65_probe(int unit);
struct net_device *sonic_probe(int unit);
struct net_device *smc_init(int unit);
struct net_device *atarilance_probe(int unit);
struct net_device *sun3lance_probe(int unit);
struct net_device *sun3_82586_probe(int unit);
struct net_device *apne_probe(int unit);
struct net_device *cs89x0_probe(int unit);
struct net_device *mvme147lance_probe(int unit);
struct net_device *tc515_probe(int unit);
struct net_device *lance_probe(int unit);
struct net_device *cops_probe(int unit);
struct net_device *ltpc_probe(void);
/* Fibre Channel adapters */
int iph5526_probe(struct net_device *dev);
/* SBNI adapters */
int sbni_probe(int unit);
+230
View File
@@ -0,0 +1,230 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_ACT_API_H
#define __NET_ACT_API_H
/*
* Public action API for classifiers/qdiscs
*/
#include <linux/refcount.h>
#include <net/sch_generic.h>
#include <net/pkt_sched.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
struct tcf_idrinfo {
spinlock_t lock;
struct idr action_idr;
struct net *net;
};
struct tc_action_ops;
struct tc_action {
const struct tc_action_ops *ops;
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
__u32 order;
struct tcf_idrinfo *idrinfo;
u32 tcfa_index;
refcount_t tcfa_refcnt;
atomic_t tcfa_bindcnt;
int tcfa_action;
struct tcf_t tcfa_tm;
struct gnet_stats_basic_packed tcfa_bstats;
struct gnet_stats_queue tcfa_qstats;
struct net_rate_estimator __rcu *tcfa_rate_est;
spinlock_t tcfa_lock;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
struct gnet_stats_queue __percpu *cpu_qstats;
struct tc_cookie __rcu *act_cookie;
struct tcf_chain *goto_chain;
};
#define tcf_index common.tcfa_index
#define tcf_refcnt common.tcfa_refcnt
#define tcf_bindcnt common.tcfa_bindcnt
#define tcf_action common.tcfa_action
#define tcf_tm common.tcfa_tm
#define tcf_bstats common.tcfa_bstats
#define tcf_qstats common.tcfa_qstats
#define tcf_rate_est common.tcfa_rate_est
#define tcf_lock common.tcfa_lock
/* Update lastuse only if needed, to avoid dirtying a cache line.
* We use a temp variable to avoid fetching jiffies twice.
*/
static inline void tcf_lastuse_update(struct tcf_t *tm)
{
unsigned long now = jiffies;
if (tm->lastuse != now)
tm->lastuse = now;
if (unlikely(!tm->firstuse))
tm->firstuse = now;
}
static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm)
{
dtm->install = jiffies_to_clock_t(jiffies - stm->install);
dtm->lastuse = jiffies_to_clock_t(jiffies - stm->lastuse);
dtm->firstuse = stm->firstuse ?
jiffies_to_clock_t(jiffies - stm->firstuse) : 0;
dtm->expires = jiffies_to_clock_t(stm->expires);
}
#ifdef CONFIG_NET_CLS_ACT
#define ACT_P_CREATED 1
#define ACT_P_DELETED 1
struct tc_action_ops {
struct list_head head;
char kind[IFNAMSIZ];
__u32 type; /* TBD to match kind */
size_t size;
struct module *owner;
int (*act)(struct sk_buff *, const struct tc_action *,
struct tcf_result *); /* called under RCU BH lock*/
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void (*cleanup)(struct tc_action *);
int (*lookup)(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
int bind, bool rtnl_held,
struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
const struct tc_action_ops *,
struct netlink_ext_ack *);
void (*stats_update)(struct tc_action *, u64, u32, u64);
size_t (*get_fill_size)(const struct tc_action *act);
struct net_device *(*get_dev)(const struct tc_action *a);
void (*put_dev)(struct net_device *dev);
};
struct tc_action_net {
struct tcf_idrinfo *idrinfo;
const struct tc_action_ops *ops;
};
static inline
int tc_action_net_init(struct net *net, struct tc_action_net *tn,
const struct tc_action_ops *ops)
{
int err = 0;
tn->idrinfo = kmalloc(sizeof(*tn->idrinfo), GFP_KERNEL);
if (!tn->idrinfo)
return -ENOMEM;
tn->ops = ops;
tn->idrinfo->net = net;
spin_lock_init(&tn->idrinfo->lock);
idr_init(&tn->idrinfo->action_idr);
return err;
}
void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
struct tcf_idrinfo *idrinfo);
static inline void tc_action_net_exit(struct list_head *net_list,
unsigned int id)
{
struct net *net;
rtnl_lock();
list_for_each_entry(net, net_list, exit_list) {
struct tc_action_net *tn = net_generic(net, id);
tcf_idrinfo_destroy(tn->ops, tn->idrinfo);
kfree(tn->idrinfo);
}
rtnl_unlock();
}
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type,
const struct tc_action_ops *ops,
struct netlink_ext_ack *extack);
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
struct tc_action **a, const struct tc_action_ops *ops,
int bind, bool cpustats);
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
struct tc_action **a, int bind);
int __tcf_idr_release(struct tc_action *a, bool bind, bool strict);
static inline int tcf_idr_release(struct tc_action *a, bool bind)
{
return __tcf_idr_release(a, bind, false);
}
int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
int tcf_unregister_action(struct tc_action_ops *a,
struct pernet_operations *ops);
int tcf_action_destroy(struct tc_action *actions[], int bind);
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
int nr_actions, struct tcf_result *res);
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
struct tc_action *actions[], size_t *attr_size,
bool rtnl_held, struct netlink_ext_ack *extack);
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
char *name, int ovr, int bind,
bool rtnl_held,
struct netlink_ext_ack *extack);
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind,
int ref);
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
#endif /* CONFIG_NET_CLS_ACT */
static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,
u64 packets, u64 lastuse)
{
#ifdef CONFIG_NET_CLS_ACT
if (!a->ops->stats_update)
return;
a->ops->stats_update(a, bytes, packets, lastuse);
#endif
}
#ifdef CONFIG_NET_CLS_ACT
int tc_setup_cb_egdev_register(const struct net_device *dev,
tc_setup_cb_t *cb, void *cb_priv);
void tc_setup_cb_egdev_unregister(const struct net_device *dev,
tc_setup_cb_t *cb, void *cb_priv);
int tc_setup_cb_egdev_call(const struct net_device *dev,
enum tc_setup_type type, void *type_data,
bool err_stop);
#else
static inline
int tc_setup_cb_egdev_register(const struct net_device *dev,
tc_setup_cb_t *cb, void *cb_priv)
{
return 0;
}
static inline
void tc_setup_cb_egdev_unregister(const struct net_device *dev,
tc_setup_cb_t *cb, void *cb_priv)
{
}
static inline
int tc_setup_cb_egdev_call(const struct net_device *dev,
enum tc_setup_type type, void *type_data,
bool err_stop)
{
return 0;
}
#endif
#endif
+505
View File
@@ -0,0 +1,505 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ADDRCONF_H
#define _ADDRCONF_H
#define MAX_RTR_SOLICITATIONS -1 /* unlimited */
#define RTR_SOLICITATION_INTERVAL (4*HZ)
#define RTR_SOLICITATION_MAX_INTERVAL (3600*HZ) /* 1 hour */
#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */
#define TEMP_VALID_LIFETIME (7*86400)
#define TEMP_PREFERRED_LIFETIME (86400)
#define REGEN_MAX_RETRY (3)
#define MAX_DESYNC_FACTOR (600)
#define ADDR_CHECK_FREQUENCY (120*HZ)
#define IPV6_MAX_ADDRESSES 16
#define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ / 50 : 1)
#define ADDRCONF_TIMER_FUZZ (HZ / 4)
#define ADDRCONF_TIMER_FUZZ_MAX (HZ)
#define ADDRCONF_NOTIFY_PRIORITY 0
#include <linux/in.h>
#include <linux/in6.h>
struct prefix_info {
__u8 type;
__u8 length;
__u8 prefix_len;
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 onlink : 1,
autoconf : 1,
reserved : 6;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
__u8 reserved : 6,
autoconf : 1,
onlink : 1;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__be32 valid;
__be32 prefered;
__be32 reserved2;
struct in6_addr prefix;
};
#include <linux/netdevice.h>
#include <net/if_inet6.h>
#include <net/ipv6.h>
struct in6_validator_info {
struct in6_addr i6vi_addr;
struct inet6_dev *i6vi_dev;
struct netlink_ext_ack *extack;
};
struct ifa6_config {
const struct in6_addr *pfx;
unsigned int plen;
const struct in6_addr *peer_pfx;
u32 rt_priority;
u32 ifa_flags;
u32 preferred_lft;
u32 valid_lft;
u16 scope;
};
int addrconf_init(void);
void addrconf_cleanup(void);
int addrconf_add_ifaddr(struct net *net, void __user *arg);
int addrconf_del_ifaddr(struct net *net, void __user *arg);
int addrconf_set_dstaddr(struct net *net, void __user *arg);
int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
const struct net_device *dev, int strict);
int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
const struct net_device *dev, bool skip_dev_check,
int strict, u32 banned_flags);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
#endif
bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
const unsigned int prefix_len,
struct net_device *dev);
int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
const struct in6_addr *addr,
struct net_device *dev, int strict);
int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
const struct in6_addr *daddr, unsigned int srcprefs,
struct in6_addr *saddr);
int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
u32 banned_flags);
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
u32 banned_flags);
bool inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
bool match_wildcard);
bool inet_rcv_saddr_any(const struct sock *sk);
void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);
void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr);
void addrconf_add_linklocal(struct inet6_dev *idev,
const struct in6_addr *addr, u32 flags);
int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
const struct prefix_info *pinfo,
struct inet6_dev *in6_dev,
const struct in6_addr *addr, int addr_type,
u32 addr_flags, bool sllao, bool tokenized,
__u32 valid_lft, u32 prefered_lft);
static inline void addrconf_addr_eui48_base(u8 *eui, const char *const addr)
{
memcpy(eui, addr, 3);
eui[3] = 0xFF;
eui[4] = 0xFE;
memcpy(eui + 5, addr + 3, 3);
}
static inline void addrconf_addr_eui48(u8 *eui, const char *const addr)
{
addrconf_addr_eui48_base(eui, addr);
eui[0] ^= 2;
}
static inline int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
{
if (dev->addr_len != ETH_ALEN)
return -1;
/*
* The zSeries OSA network cards can be shared among various
* OS instances, but the OSA cards have only one MAC address.
* This leads to duplicate address conflicts in conjunction
* with IPv6 if more than one instance uses the same card.
*
* The driver for these cards can deliver a unique 16-bit
* identifier for each instance sharing the same card. It is
* placed instead of 0xFFFE in the interface identifier. The
* "u" bit of the interface identifier is not inverted in this
* case. Hence the resulting interface identifier has local
* scope according to RFC2373.
*/
addrconf_addr_eui48_base(eui, dev->dev_addr);
if (dev->dev_id) {
eui[3] = (dev->dev_id >> 8) & 0xFF;
eui[4] = dev->dev_id & 0xFF;
} else {
eui[0] ^= 2;
}
return 0;
}
static inline unsigned long addrconf_timeout_fixup(u32 timeout,
unsigned int unit)
{
if (timeout == 0xffffffff)
return ~0UL;
/*
* Avoid arithmetic overflow.
* Assuming unit is constant and non-zero, this "if" statement
* will go away on 64bit archs.
*/
if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit)
return LONG_MAX / unit;
return timeout;
}
static inline int addrconf_finite_timeout(unsigned long timeout)
{
return ~timeout;
}
/*
* IPv6 Address Label subsystem (addrlabel.c)
*/
int ipv6_addr_label_init(void);
void ipv6_addr_label_cleanup(void);
int ipv6_addr_label_rtnl_register(void);
u32 ipv6_addr_label(struct net *net, const struct in6_addr *addr,
int type, int ifindex);
/*
* multicast prototypes (mcast.c)
*/
int ipv6_sock_mc_join(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
const struct in6_addr *addr);
void __ipv6_sock_mc_close(struct sock *sk);
void ipv6_sock_mc_close(struct sock *sk);
bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
const struct in6_addr *src_addr);
int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
void ipv6_mc_up(struct inet6_dev *idev);
void ipv6_mc_down(struct inet6_dev *idev);
void ipv6_mc_unmap(struct inet6_dev *idev);
void ipv6_mc_remap(struct inet6_dev *idev);
void ipv6_mc_init_dev(struct inet6_dev *idev);
void ipv6_mc_destroy_dev(struct inet6_dev *idev);
int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed);
void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp);
bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
const struct in6_addr *src_addr);
void ipv6_mc_dad_complete(struct inet6_dev *idev);
/* A stub used by vxlan module. This is ugly, ideally these
* symbols should be built into the core kernel.
*/
struct ipv6_stub {
int (*ipv6_sock_mc_join)(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
const struct in6_addr *addr);
struct dst_entry *(*ipv6_dst_lookup_flow)(struct net *net,
const struct sock *sk,
struct flowi6 *fl6,
const struct in6_addr *final_dst);
struct fib6_table *(*fib6_get_table)(struct net *net, u32 id);
struct fib6_info *(*fib6_lookup)(struct net *net, int oif,
struct flowi6 *fl6, int flags);
struct fib6_info *(*fib6_table_lookup)(struct net *net,
struct fib6_table *table,
int oif, struct flowi6 *fl6,
int flags);
struct fib6_info *(*fib6_multipath_select)(const struct net *net,
struct fib6_info *f6i,
struct flowi6 *fl6, int oif,
const struct sk_buff *skb,
int strict);
u32 (*ip6_mtu_from_fib6)(struct fib6_info *f6i, struct in6_addr *daddr,
struct in6_addr *saddr);
void (*udpv6_encap_enable)(void);
void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
const struct in6_addr *solicited_addr,
bool router, bool solicited, bool override, bool inc_opt);
struct neigh_table *nd_tbl;
};
extern const struct ipv6_stub *ipv6_stub __read_mostly;
/* A stub used by bpf helpers. Similarly ugly as ipv6_stub */
struct ipv6_bpf_stub {
int (*inet6_bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len,
bool force_bind_address_no_port, bool with_lock);
};
extern const struct ipv6_bpf_stub *ipv6_bpf_stub __read_mostly;
/*
* identify MLD packets for MLD filter exceptions
*/
static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset)
{
struct icmp6hdr *hdr;
if (nexthdr != IPPROTO_ICMPV6 ||
!pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr)))
return false;
hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset);
switch (hdr->icmp6_type) {
case ICMPV6_MGM_QUERY:
case ICMPV6_MGM_REPORT:
case ICMPV6_MGM_REDUCTION:
case ICMPV6_MLD2_REPORT:
return true;
default:
break;
}
return false;
}
void addrconf_prefix_rcv(struct net_device *dev,
u8 *opt, int len, bool sllao);
/* Determines into what table to put autoconf PIO/RIO/default routes
* learned on this device.
*
* - If 0, use the same table for every device. This puts routes into
* one of RT_TABLE_{PREFIX,INFO,DFLT} depending on the type of route
* (but note that these three are currently all equal to
* RT6_TABLE_MAIN).
* - If > 0, use the specified table.
* - If < 0, put routes into table dev->ifindex + (-rt_table).
*/
u32 addrconf_rt_table(const struct net_device *dev, u32 default_table);
/*
* anycast prototypes (anycast.c)
*/
int ipv6_sock_ac_join(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int ipv6_sock_ac_drop(struct sock *sk, int ifindex,
const struct in6_addr *addr);
void __ipv6_sock_ac_close(struct sock *sk);
void ipv6_sock_ac_close(struct sock *sk);
int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr);
int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
void ipv6_ac_destroy_dev(struct inet6_dev *idev);
bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
const struct in6_addr *addr);
bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev,
const struct in6_addr *addr);
/* Device notifier */
int register_inet6addr_notifier(struct notifier_block *nb);
int unregister_inet6addr_notifier(struct notifier_block *nb);
int inet6addr_notifier_call_chain(unsigned long val, void *v);
int register_inet6addr_validator_notifier(struct notifier_block *nb);
int unregister_inet6addr_validator_notifier(struct notifier_block *nb);
int inet6addr_validator_notifier_call_chain(unsigned long val, void *v);
void inet6_netconf_notify_devconf(struct net *net, int event, int type,
int ifindex, struct ipv6_devconf *devconf);
/**
* __in6_dev_get - get inet6_dev pointer from netdevice
* @dev: network device
*
* Caller must hold rcu_read_lock or RTNL, because this function
* does not take a reference on the inet6_dev.
*/
static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
{
return rcu_dereference_rtnl(dev->ip6_ptr);
}
/**
* __in6_dev_get_safely - get inet6_dev pointer from netdevice
* @dev: network device
*
* This is a safer version of __in6_dev_get
*/
static inline struct inet6_dev *__in6_dev_get_safely(const struct net_device *dev)
{
if (likely(dev))
return rcu_dereference_rtnl(dev->ip6_ptr);
else
return NULL;
}
/**
* in6_dev_get - get inet6_dev pointer from netdevice
* @dev: network device
*
* This version can be used in any context, and takes a reference
* on the inet6_dev. Callers must use in6_dev_put() later to
* release this reference.
*/
static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
{
struct inet6_dev *idev;
rcu_read_lock();
idev = rcu_dereference(dev->ip6_ptr);
if (idev)
refcount_inc(&idev->refcnt);
rcu_read_unlock();
return idev;
}
static inline struct neigh_parms *__in6_dev_nd_parms_get_rcu(const struct net_device *dev)
{
struct inet6_dev *idev = __in6_dev_get(dev);
return idev ? idev->nd_parms : NULL;
}
void in6_dev_finish_destroy(struct inet6_dev *idev);
static inline void in6_dev_put(struct inet6_dev *idev)
{
if (refcount_dec_and_test(&idev->refcnt))
in6_dev_finish_destroy(idev);
}
static inline void in6_dev_put_clear(struct inet6_dev **pidev)
{
struct inet6_dev *idev = *pidev;
if (idev) {
in6_dev_put(idev);
*pidev = NULL;
}
}
static inline void __in6_dev_put(struct inet6_dev *idev)
{
refcount_dec(&idev->refcnt);
}
static inline void in6_dev_hold(struct inet6_dev *idev)
{
refcount_inc(&idev->refcnt);
}
void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
{
if (refcount_dec_and_test(&ifp->refcnt))
inet6_ifa_finish_destroy(ifp);
}
static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
{
refcount_dec(&ifp->refcnt);
}
static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
{
refcount_inc(&ifp->refcnt);
}
/*
* compute link-local solicited-node multicast address
*/
static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
struct in6_addr *solicited)
{
ipv6_addr_set(solicited,
htonl(0xFF020000), 0,
htonl(0x1),
htonl(0xFF000000) | addr->s6_addr32[3]);
}
static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
__be64 *p = (__be64 *)addr;
return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL;
#else
return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
addr->s6_addr32[1] | addr->s6_addr32[2] |
(addr->s6_addr32[3] ^ htonl(0x00000001))) == 0;
#endif
}
static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
__be64 *p = (__be64 *)addr;
return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL;
#else
return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
addr->s6_addr32[1] | addr->s6_addr32[2] |
(addr->s6_addr32[3] ^ htonl(0x00000002))) == 0;
#endif
}
static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
{
return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
}
static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
__be64 *p = (__be64 *)addr;
return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) |
((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) &
cpu_to_be64(0xffffffffff000000UL))) == 0UL;
#else
return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
addr->s6_addr32[1] |
(addr->s6_addr32[2] ^ htonl(0x00000001)) |
(addr->s6_addr[12] ^ 0xff)) == 0;
#endif
}
#ifdef CONFIG_PROC_FS
int if6_proc_init(void);
void if6_proc_exit(void);
#endif
#endif
+67
View File
@@ -0,0 +1,67 @@
/*
* IEEE 802.15.4 interface for userspace
*
* Copyright 2007, 2008 Siemens AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
*/
#ifndef _AF_IEEE802154_H
#define _AF_IEEE802154_H
#include <linux/socket.h> /* for sa_family_t */
enum {
IEEE802154_ADDR_NONE = 0x0,
/* RESERVED = 0x01, */
IEEE802154_ADDR_SHORT = 0x2, /* 16-bit address + PANid */
IEEE802154_ADDR_LONG = 0x3, /* 64-bit address + PANid */
};
/* address length, octets */
#define IEEE802154_ADDR_LEN 8
struct ieee802154_addr_sa {
int addr_type;
u16 pan_id;
union {
u8 hwaddr[IEEE802154_ADDR_LEN];
u16 short_addr;
};
};
#define IEEE802154_PANID_BROADCAST 0xffff
#define IEEE802154_ADDR_BROADCAST 0xffff
#define IEEE802154_ADDR_UNDEF 0xfffe
struct sockaddr_ieee802154 {
sa_family_t family; /* AF_IEEE802154 */
struct ieee802154_addr_sa addr;
};
/* get/setsockopt */
#define SOL_IEEE802154 0
#define WPAN_WANTACK 0
#define WPAN_SECURITY 1
#define WPAN_SECURITY_LEVEL 2
#define WPAN_WANTLQI 3
#define WPAN_SECURITY_DEFAULT 0
#define WPAN_SECURITY_OFF 1
#define WPAN_SECURITY_ON 2
#define WPAN_SECURITY_LEVEL_DEFAULT (-1)
#endif
+81
View File
@@ -0,0 +1,81 @@
/* RxRPC kernel service interface definitions
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _NET_RXRPC_H
#define _NET_RXRPC_H
#include <linux/rxrpc.h>
struct key;
struct sock;
struct socket;
struct rxrpc_call;
/*
* Call completion condition (state == RXRPC_CALL_COMPLETE).
*/
enum rxrpc_call_completion {
RXRPC_CALL_SUCCEEDED, /* - Normal termination */
RXRPC_CALL_REMOTELY_ABORTED, /* - call aborted by peer */
RXRPC_CALL_LOCALLY_ABORTED, /* - call aborted locally on error or close */
RXRPC_CALL_LOCAL_ERROR, /* - call failed due to local error */
RXRPC_CALL_NETWORK_ERROR, /* - call terminated by network error */
NR__RXRPC_CALL_COMPLETIONS
};
/*
* Debug ID counter for tracing.
*/
extern atomic_t rxrpc_debug_id;
typedef void (*rxrpc_notify_rx_t)(struct sock *, struct rxrpc_call *,
unsigned long);
typedef void (*rxrpc_notify_end_tx_t)(struct sock *, struct rxrpc_call *,
unsigned long);
typedef void (*rxrpc_notify_new_call_t)(struct sock *, struct rxrpc_call *,
unsigned long);
typedef void (*rxrpc_discard_new_call_t)(struct rxrpc_call *, unsigned long);
typedef void (*rxrpc_user_attach_call_t)(struct rxrpc_call *, unsigned long);
void rxrpc_kernel_new_call_notification(struct socket *,
rxrpc_notify_new_call_t,
rxrpc_discard_new_call_t);
struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
struct sockaddr_rxrpc *,
struct key *,
unsigned long,
s64,
gfp_t,
rxrpc_notify_rx_t,
bool,
unsigned int);
int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
struct msghdr *, size_t,
rxrpc_notify_end_tx_t);
int rxrpc_kernel_recv_data(struct socket *, struct rxrpc_call *,
struct iov_iter *, bool, u32 *, u16 *);
bool rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *,
u32, int, const char *);
void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *);
void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
struct sockaddr_rxrpc *);
u64 rxrpc_kernel_get_rtt(struct socket *, struct rxrpc_call *);
int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
rxrpc_user_attach_call_t, unsigned long, gfp_t,
unsigned int);
void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
struct sockaddr_rxrpc *, struct key *);
int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
enum rxrpc_call_completion *, u32 *);
u32 rxrpc_kernel_check_life(struct socket *, struct rxrpc_call *);
#endif /* _NET_RXRPC_H */
+87
View File
@@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_NET_AFUNIX_H
#define __LINUX_NET_AFUNIX_H
#include <linux/socket.h>
#include <linux/un.h>
#include <linux/mutex.h>
#include <linux/refcount.h>
#include <net/sock.h>
void unix_inflight(struct user_struct *user, struct file *fp);
void unix_notinflight(struct user_struct *user, struct file *fp);
void unix_destruct_scm(struct sk_buff *skb);
void unix_gc(void);
void wait_for_unix_gc(void);
struct sock *unix_get_socket(struct file *filp);
struct sock *unix_peer_get(struct sock *);
#define UNIX_HASH_SIZE 256
#define UNIX_HASH_BITS 8
extern unsigned int unix_tot_inflight;
extern spinlock_t unix_table_lock;
extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
struct unix_address {
refcount_t refcnt;
int len;
unsigned int hash;
struct sockaddr_un name[0];
};
struct unix_skb_parms {
struct pid *pid; /* Skb credentials */
kuid_t uid;
kgid_t gid;
struct scm_fp_list *fp; /* Passed files */
#ifdef CONFIG_SECURITY_NETWORK
u32 secid; /* Security ID */
#endif
u32 consumed;
} __randomize_layout;
#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb))
#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
#define unix_state_lock_nested(s) \
spin_lock_nested(&unix_sk(s)->lock, \
SINGLE_DEPTH_NESTING)
/* The AF_UNIX socket */
struct unix_sock {
/* WARNING: sk has to be the first member */
struct sock sk;
struct unix_address *addr;
struct path path;
struct mutex iolock, bindlock;
struct sock *peer;
struct list_head link;
unsigned long inflight;
spinlock_t lock;
unsigned long gc_flags;
#define UNIX_GC_CANDIDATE 0
#define UNIX_GC_MAYBE_CYCLE 1
struct socket_wq peer_wq;
wait_queue_entry_t peer_wake;
};
static inline struct unix_sock *unix_sk(const struct sock *sk)
{
return (struct unix_sock *)sk;
}
#define peer_wait peer_wq.wait
long unix_inq_len(struct sock *sk);
long unix_outq_len(struct sock *sk);
#ifdef CONFIG_SYSCTL
int unix_sysctl_register(struct net *net);
void unix_sysctl_unregister(struct net *net);
#else
static inline int unix_sysctl_register(struct net *net) { return 0; }
static inline void unix_sysctl_unregister(struct net *net) {}
#endif
#endif
+218
View File
@@ -0,0 +1,218 @@
/*
* VMware vSockets Driver
*
* Copyright (C) 2007-2013 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __AF_VSOCK_H__
#define __AF_VSOCK_H__
#include <linux/kernel.h>
#include <linux/workqueue.h>
#include <linux/vm_sockets.h>
#include "vsock_addr.h"
#define LAST_RESERVED_PORT 1023
#define VSOCK_HASH_SIZE 251
extern struct list_head vsock_bind_table[VSOCK_HASH_SIZE + 1];
extern struct list_head vsock_connected_table[VSOCK_HASH_SIZE];
extern spinlock_t vsock_table_lock;
#define vsock_sk(__sk) ((struct vsock_sock *)__sk)
#define sk_vsock(__vsk) (&(__vsk)->sk)
struct vsock_sock {
/* sk must be the first member. */
struct sock sk;
struct sockaddr_vm local_addr;
struct sockaddr_vm remote_addr;
/* Links for the global tables of bound and connected sockets. */
struct list_head bound_table;
struct list_head connected_table;
/* Accessed without the socket lock held. This means it can never be
* modified outsided of socket create or destruct.
*/
bool trusted;
bool cached_peer_allow_dgram; /* Dgram communication allowed to
* cached peer?
*/
u32 cached_peer; /* Context ID of last dgram destination check. */
const struct cred *owner;
/* Rest are SOCK_STREAM only. */
long connect_timeout;
/* Listening socket that this came from. */
struct sock *listener;
/* Used for pending list and accept queue during connection handshake.
* The listening socket is the head for both lists. Sockets created
* for connection requests are placed in the pending list until they
* are connected, at which point they are put in the accept queue list
* so they can be accepted in accept(). If accept() cannot accept the
* connection, it is marked as rejected so the cleanup function knows
* to clean up the socket.
*/
struct list_head pending_links;
struct list_head accept_queue;
bool rejected;
struct delayed_work connect_work;
struct delayed_work pending_work;
struct delayed_work close_work;
bool close_work_scheduled;
u32 peer_shutdown;
bool sent_request;
bool ignore_connecting_rst;
/* Private to transport. */
void *trans;
};
s64 vsock_stream_has_data(struct vsock_sock *vsk);
s64 vsock_stream_has_space(struct vsock_sock *vsk);
struct sock *__vsock_create(struct net *net,
struct socket *sock,
struct sock *parent,
gfp_t priority, unsigned short type, int kern);
/**** TRANSPORT ****/
struct vsock_transport_recv_notify_data {
u64 data1; /* Transport-defined. */
u64 data2; /* Transport-defined. */
bool notify_on_block;
};
struct vsock_transport_send_notify_data {
u64 data1; /* Transport-defined. */
u64 data2; /* Transport-defined. */
};
struct vsock_transport {
/* Initialize/tear-down socket. */
int (*init)(struct vsock_sock *, struct vsock_sock *);
void (*destruct)(struct vsock_sock *);
void (*release)(struct vsock_sock *);
/* Cancel all pending packets sent on vsock. */
int (*cancel_pkt)(struct vsock_sock *vsk);
/* Connections. */
int (*connect)(struct vsock_sock *);
/* DGRAM. */
int (*dgram_bind)(struct vsock_sock *, struct sockaddr_vm *);
int (*dgram_dequeue)(struct vsock_sock *vsk, struct msghdr *msg,
size_t len, int flags);
int (*dgram_enqueue)(struct vsock_sock *, struct sockaddr_vm *,
struct msghdr *, size_t len);
bool (*dgram_allow)(u32 cid, u32 port);
/* STREAM. */
/* TODO: stream_bind() */
ssize_t (*stream_dequeue)(struct vsock_sock *, struct msghdr *,
size_t len, int flags);
ssize_t (*stream_enqueue)(struct vsock_sock *, struct msghdr *,
size_t len);
s64 (*stream_has_data)(struct vsock_sock *);
s64 (*stream_has_space)(struct vsock_sock *);
u64 (*stream_rcvhiwat)(struct vsock_sock *);
bool (*stream_is_active)(struct vsock_sock *);
bool (*stream_allow)(u32 cid, u32 port);
/* Notification. */
int (*notify_poll_in)(struct vsock_sock *, size_t, bool *);
int (*notify_poll_out)(struct vsock_sock *, size_t, bool *);
int (*notify_recv_init)(struct vsock_sock *, size_t,
struct vsock_transport_recv_notify_data *);
int (*notify_recv_pre_block)(struct vsock_sock *, size_t,
struct vsock_transport_recv_notify_data *);
int (*notify_recv_pre_dequeue)(struct vsock_sock *, size_t,
struct vsock_transport_recv_notify_data *);
int (*notify_recv_post_dequeue)(struct vsock_sock *, size_t,
ssize_t, bool, struct vsock_transport_recv_notify_data *);
int (*notify_send_init)(struct vsock_sock *,
struct vsock_transport_send_notify_data *);
int (*notify_send_pre_block)(struct vsock_sock *,
struct vsock_transport_send_notify_data *);
int (*notify_send_pre_enqueue)(struct vsock_sock *,
struct vsock_transport_send_notify_data *);
int (*notify_send_post_enqueue)(struct vsock_sock *, ssize_t,
struct vsock_transport_send_notify_data *);
/* Shutdown. */
int (*shutdown)(struct vsock_sock *, int);
/* Buffer sizes. */
void (*set_buffer_size)(struct vsock_sock *, u64);
void (*set_min_buffer_size)(struct vsock_sock *, u64);
void (*set_max_buffer_size)(struct vsock_sock *, u64);
u64 (*get_buffer_size)(struct vsock_sock *);
u64 (*get_min_buffer_size)(struct vsock_sock *);
u64 (*get_max_buffer_size)(struct vsock_sock *);
/* Addressing. */
u32 (*get_local_cid)(void);
};
/**** CORE ****/
int __vsock_core_init(const struct vsock_transport *t, struct module *owner);
static inline int vsock_core_init(const struct vsock_transport *t)
{
return __vsock_core_init(t, THIS_MODULE);
}
void vsock_core_exit(void);
/* The transport may downcast this to access transport-specific functions */
const struct vsock_transport *vsock_core_get_transport(void);
/**** UTILS ****/
/* vsock_table_lock must be held */
static inline bool __vsock_in_bound_table(struct vsock_sock *vsk)
{
return !list_empty(&vsk->bound_table);
}
/* vsock_table_lock must be held */
static inline bool __vsock_in_connected_table(struct vsock_sock *vsk)
{
return !list_empty(&vsk->connected_table);
}
void vsock_release_pending(struct sock *pending);
void vsock_add_pending(struct sock *listener, struct sock *pending);
void vsock_remove_pending(struct sock *listener, struct sock *pending);
void vsock_enqueue_accept(struct sock *listener, struct sock *connected);
void vsock_insert_connected(struct vsock_sock *vsk);
void vsock_remove_bound(struct vsock_sock *vsk);
void vsock_remove_connected(struct vsock_sock *vsk);
struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
struct sockaddr_vm *dst);
void vsock_remove_sock(struct vsock_sock *vsk);
void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
/**** TAP ****/
struct vsock_tap {
struct net_device *dev;
struct module *module;
struct list_head list;
};
int vsock_init_tap(void);
int vsock_add_tap(struct vsock_tap *vt);
int vsock_remove_tap(struct vsock_tap *vt);
void vsock_deliver_tap(struct sk_buff *build_skb(void *opaque), void *opaque);
#endif /* __AF_VSOCK_H__ */
+23
View File
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_AH_H
#define _NET_AH_H
#include <linux/skbuff.h>
struct crypto_ahash;
struct ah_data {
int icv_full_len;
int icv_trunc_len;
struct crypto_ahash *ahash;
};
struct ip_auth_hdr;
static inline struct ip_auth_hdr *ip_auth_hdr(const struct sk_buff *skb)
{
return (struct ip_auth_hdr *)skb_transport_header(skb);
}
#endif
+82
View File
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* linux/net/inet/arp.h */
#ifndef _ARP_H
#define _ARP_H
#include <linux/if_arp.h>
#include <linux/hash.h>
#include <net/neighbour.h>
extern struct neigh_table arp_tbl;
static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32 *hash_rnd)
{
u32 key = *(const u32 *)pkey;
u32 val = key ^ hash32_ptr(dev);
return val * hash_rnd[0];
}
#ifdef CONFIG_INET
static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
{
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
key = INADDR_ANY;
return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev);
}
#else
static inline
struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
{
return NULL;
}
#endif
static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
{
struct neighbour *n;
rcu_read_lock_bh();
n = __ipv4_neigh_lookup_noref(dev, key);
if (n && !refcount_inc_not_zero(&n->refcnt))
n = NULL;
rcu_read_unlock_bh();
return n;
}
static inline void __ipv4_confirm_neigh(struct net_device *dev, u32 key)
{
struct neighbour *n;
rcu_read_lock_bh();
n = __ipv4_neigh_lookup_noref(dev, key);
if (n) {
unsigned long now = jiffies;
/* avoid dirtying neighbour */
if (n->confirmed != now)
n->confirmed = now;
}
rcu_read_unlock_bh();
}
void arp_init(void);
int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
void arp_send(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
const unsigned char *dest_hw,
const unsigned char *src_hw, const unsigned char *th);
int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
void arp_ifdown(struct net_device *dev);
struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
const unsigned char *dest_hw,
const unsigned char *src_hw,
const unsigned char *target_hw);
void arp_xmit(struct sk_buff *skb);
#endif /* _ARP_H */
+53
View File
@@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* net/atm/atmarp.h - RFC1577 ATM ARP */
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
#ifndef _ATMCLIP_H
#define _ATMCLIP_H
#include <linux/netdevice.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmarp.h>
#include <linux/spinlock.h>
#include <net/neighbour.h>
#define CLIP_VCC(vcc) ((struct clip_vcc *) ((vcc)->user_back))
struct sk_buff;
struct clip_vcc {
struct atm_vcc *vcc; /* VCC descriptor */
struct atmarp_entry *entry; /* ATMARP table entry, NULL if IP addr.
isn't known yet */
int xoff; /* 1 if send buffer is full */
unsigned char encap; /* 0: NULL, 1: LLC/SNAP */
unsigned long last_use; /* last send or receive operation */
unsigned long idle_timeout; /* keep open idle for so many jiffies*/
void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
/* keep old push fn for chaining */
void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb);
/* keep old pop fn for chaining */
struct clip_vcc *next; /* next VCC */
};
struct atmarp_entry {
struct clip_vcc *vccs; /* active VCCs; NULL if resolution is
pending */
unsigned long expires; /* entry expiration time */
struct neighbour *neigh; /* neighbour back-pointer */
};
#define PRIV(dev) ((struct clip_priv *) netdev_priv(dev))
struct clip_priv {
int number; /* for convenience ... */
spinlock_t xoff_lock; /* ensures that pop is atomic (SMP) */
struct net_device *next; /* next CLIP interface */
};
#endif
+483
View File
@@ -0,0 +1,483 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Declarations of AX.25 type objects.
*
* Alan Cox (GW4PTS) 10/11/93
*/
#ifndef _AX25_H
#define _AX25_H
#include <linux/ax25.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/refcount.h>
#include <net/neighbour.h>
#include <net/sock.h>
#include <linux/seq_file.h>
#define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPHI (30 * HZ)
#define AX25_BPQ_HEADER_LEN 16
#define AX25_KISS_HEADER_LEN 1
#define AX25_HEADER_LEN 17
#define AX25_ADDR_LEN 7
#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN)
#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN)
/* AX.25 Protocol IDs */
#define AX25_P_ROSE 0x01
#define AX25_P_VJCOMP 0x06 /* Compressed TCP/IP packet */
/* Van Jacobsen (RFC 1144) */
#define AX25_P_VJUNCOMP 0x07 /* Uncompressed TCP/IP packet */
/* Van Jacobsen (RFC 1144) */
#define AX25_P_SEGMENT 0x08 /* Segmentation fragment */
#define AX25_P_TEXNET 0xc3 /* TEXTNET datagram protocol */
#define AX25_P_LQ 0xc4 /* Link Quality Protocol */
#define AX25_P_ATALK 0xca /* Appletalk */
#define AX25_P_ATALK_ARP 0xcb /* Appletalk ARP */
#define AX25_P_IP 0xcc /* ARPA Internet Protocol */
#define AX25_P_ARP 0xcd /* ARPA Address Resolution */
#define AX25_P_FLEXNET 0xce /* FlexNet */
#define AX25_P_NETROM 0xcf /* NET/ROM */
#define AX25_P_TEXT 0xF0 /* No layer 3 protocol impl. */
/* AX.25 Segment control values */
#define AX25_SEG_REM 0x7F
#define AX25_SEG_FIRST 0x80
#define AX25_CBIT 0x80 /* Command/Response bit */
#define AX25_EBIT 0x01 /* HDLC Address Extension bit */
#define AX25_HBIT 0x80 /* Has been repeated bit */
#define AX25_SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */
#define AX25_ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */
#define AX25_DAMA_FLAG 0x20 /* Well, it is *NOT* unused! (dl1bke 951121 */
#define AX25_COND_ACK_PENDING 0x01
#define AX25_COND_REJECT 0x02
#define AX25_COND_PEER_RX_BUSY 0x04
#define AX25_COND_OWN_RX_BUSY 0x08
#define AX25_COND_DAMA_MODE 0x10
#ifndef _LINUX_NETDEVICE_H
#include <linux/netdevice.h>
#endif
/* Upper sub-layer (LAPB) definitions */
/* Control field templates */
#define AX25_I 0x00 /* Information frames */
#define AX25_S 0x01 /* Supervisory frames */
#define AX25_RR 0x01 /* Receiver ready */
#define AX25_RNR 0x05 /* Receiver not ready */
#define AX25_REJ 0x09 /* Reject */
#define AX25_U 0x03 /* Unnumbered frames */
#define AX25_SABM 0x2f /* Set Asynchronous Balanced Mode */
#define AX25_SABME 0x6f /* Set Asynchronous Balanced Mode Extended */
#define AX25_DISC 0x43 /* Disconnect */
#define AX25_DM 0x0f /* Disconnected mode */
#define AX25_UA 0x63 /* Unnumbered acknowledge */
#define AX25_FRMR 0x87 /* Frame reject */
#define AX25_UI 0x03 /* Unnumbered information */
#define AX25_XID 0xaf /* Exchange information */
#define AX25_TEST 0xe3 /* Test */
#define AX25_PF 0x10 /* Poll/final bit for standard AX.25 */
#define AX25_EPF 0x01 /* Poll/final bit for extended AX.25 */
#define AX25_ILLEGAL 0x100 /* Impossible to be a real frame type */
#define AX25_POLLOFF 0
#define AX25_POLLON 1
/* AX25 L2 C-bit */
#define AX25_COMMAND 1
#define AX25_RESPONSE 2
/* Define Link State constants. */
enum {
AX25_STATE_0, /* Listening */
AX25_STATE_1, /* SABM sent */
AX25_STATE_2, /* DISC sent */
AX25_STATE_3, /* Established */
AX25_STATE_4 /* Recovery */
};
#define AX25_MODULUS 8 /* Standard AX.25 modulus */
#define AX25_EMODULUS 128 /* Extended AX.25 modulus */
enum {
AX25_PROTO_STD_SIMPLEX,
AX25_PROTO_STD_DUPLEX,
#ifdef CONFIG_AX25_DAMA_SLAVE
AX25_PROTO_DAMA_SLAVE,
#ifdef CONFIG_AX25_DAMA_MASTER
AX25_PROTO_DAMA_MASTER,
#define AX25_PROTO_MAX AX25_PROTO_DAMA_MASTER
#endif
#endif
__AX25_PROTO_MAX,
AX25_PROTO_MAX = __AX25_PROTO_MAX -1
};
enum {
AX25_VALUES_IPDEFMODE, /* 0=DG 1=VC */
AX25_VALUES_AXDEFMODE, /* 0=Normal 1=Extended Seq Nos */
AX25_VALUES_BACKOFF, /* 0=None 1=Linear 2=Exponential */
AX25_VALUES_CONMODE, /* Allow connected modes - 0=No 1=no "PID text" 2=all PIDs */
AX25_VALUES_WINDOW, /* Default window size for standard AX.25 */
AX25_VALUES_EWINDOW, /* Default window size for extended AX.25 */
AX25_VALUES_T1, /* Default T1 timeout value */
AX25_VALUES_T2, /* Default T2 timeout value */
AX25_VALUES_T3, /* Default T3 timeout value */
AX25_VALUES_IDLE, /* Connected mode idle timer */
AX25_VALUES_N2, /* Default N2 value */
AX25_VALUES_PACLEN, /* AX.25 MTU */
AX25_VALUES_PROTOCOL, /* Std AX.25, DAMA Slave, DAMA Master */
AX25_VALUES_DS_TIMEOUT, /* DAMA Slave timeout */
AX25_MAX_VALUES /* THIS MUST REMAIN THE LAST ENTRY OF THIS LIST */
};
#define AX25_DEF_IPDEFMODE 0 /* Datagram */
#define AX25_DEF_AXDEFMODE 0 /* Normal */
#define AX25_DEF_BACKOFF 1 /* Linear backoff */
#define AX25_DEF_CONMODE 2 /* Connected mode allowed */
#define AX25_DEF_WINDOW 2 /* Window=2 */
#define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */
#define AX25_DEF_T1 10000 /* T1=10s */
#define AX25_DEF_T2 3000 /* T2=3s */
#define AX25_DEF_T3 300000 /* T3=300s */
#define AX25_DEF_N2 10 /* N2=10 */
#define AX25_DEF_IDLE 0 /* Idle=None */
#define AX25_DEF_PACLEN 256 /* Paclen=256 */
#define AX25_DEF_PROTOCOL AX25_PROTO_STD_SIMPLEX /* Standard AX.25 */
#define AX25_DEF_DS_TIMEOUT 180000 /* DAMA timeout 3 minutes */
typedef struct ax25_uid_assoc {
struct hlist_node uid_node;
refcount_t refcount;
kuid_t uid;
ax25_address call;
} ax25_uid_assoc;
#define ax25_uid_for_each(__ax25, list) \
hlist_for_each_entry(__ax25, list, uid_node)
#define ax25_uid_hold(ax25) \
refcount_inc(&((ax25)->refcount))
static inline void ax25_uid_put(ax25_uid_assoc *assoc)
{
if (refcount_dec_and_test(&assoc->refcount)) {
kfree(assoc);
}
}
typedef struct {
ax25_address calls[AX25_MAX_DIGIS];
unsigned char repeated[AX25_MAX_DIGIS];
unsigned char ndigi;
signed char lastrepeat;
} ax25_digi;
typedef struct ax25_route {
struct ax25_route *next;
refcount_t refcount;
ax25_address callsign;
struct net_device *dev;
ax25_digi *digipeat;
char ip_mode;
} ax25_route;
static inline void ax25_hold_route(ax25_route *ax25_rt)
{
refcount_inc(&ax25_rt->refcount);
}
void __ax25_put_route(ax25_route *ax25_rt);
extern rwlock_t ax25_route_lock;
static inline void ax25_route_lock_use(void)
{
read_lock(&ax25_route_lock);
}
static inline void ax25_route_lock_unuse(void)
{
read_unlock(&ax25_route_lock);
}
static inline void ax25_put_route(ax25_route *ax25_rt)
{
if (refcount_dec_and_test(&ax25_rt->refcount))
__ax25_put_route(ax25_rt);
}
typedef struct {
char slave; /* slave_mode? */
struct timer_list slave_timer; /* timeout timer */
unsigned short slave_timeout; /* when? */
} ax25_dama_info;
struct ctl_table;
typedef struct ax25_dev {
struct ax25_dev *next;
struct net_device *dev;
struct net_device *forward;
struct ctl_table_header *sysheader;
int values[AX25_MAX_VALUES];
#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
ax25_dama_info dama;
#endif
} ax25_dev;
typedef struct ax25_cb {
struct hlist_node ax25_node;
ax25_address source_addr, dest_addr;
ax25_digi *digipeat;
ax25_dev *ax25_dev;
unsigned char iamdigi;
unsigned char state, modulus, pidincl;
unsigned short vs, vr, va;
unsigned char condition, backoff;
unsigned char n2, n2count;
struct timer_list t1timer, t2timer, t3timer, idletimer;
unsigned long t1, t2, t3, idle, rtt;
unsigned short paclen, fragno, fraglen;
struct sk_buff_head write_queue;
struct sk_buff_head reseq_queue;
struct sk_buff_head ack_queue;
struct sk_buff_head frag_queue;
unsigned char window;
struct timer_list timer, dtimer;
struct sock *sk; /* Backlink to socket */
refcount_t refcount;
} ax25_cb;
struct ax25_sock {
struct sock sk;
struct ax25_cb *cb;
};
static inline struct ax25_sock *ax25_sk(const struct sock *sk)
{
return (struct ax25_sock *) sk;
}
static inline struct ax25_cb *sk_to_ax25(const struct sock *sk)
{
return ax25_sk(sk)->cb;
}
#define ax25_for_each(__ax25, list) \
hlist_for_each_entry(__ax25, list, ax25_node)
#define ax25_cb_hold(__ax25) \
refcount_inc(&((__ax25)->refcount))
static __inline__ void ax25_cb_put(ax25_cb *ax25)
{
if (refcount_dec_and_test(&ax25->refcount)) {
kfree(ax25->digipeat);
kfree(ax25);
}
}
static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
skb->dev = dev;
skb_reset_mac_header(skb);
skb->pkt_type = PACKET_HOST;
return htons(ETH_P_AX25);
}
/* af_ax25.c */
extern struct hlist_head ax25_list;
extern spinlock_t ax25_list_lock;
void ax25_cb_add(ax25_cb *);
struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *,
struct net_device *);
void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
void ax25_destroy_socket(ax25_cb *);
ax25_cb * __must_check ax25_create_cb(void);
void ax25_fillin_cb(ax25_cb *, ax25_dev *);
struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
/* ax25_addr.c */
extern const ax25_address ax25_bcast;
extern const ax25_address ax25_defaddr;
extern const ax25_address null_ax25_address;
char *ax2asc(char *buf, const ax25_address *);
void asc2ax(ax25_address *addr, const char *callsign);
int ax25cmp(const ax25_address *, const ax25_address *);
int ax25digicmp(const ax25_digi *, const ax25_digi *);
const unsigned char *ax25_addr_parse(const unsigned char *, int,
ax25_address *, ax25_address *, ax25_digi *, int *, int *);
int ax25_addr_build(unsigned char *, const ax25_address *,
const ax25_address *, const ax25_digi *, int, int);
int ax25_addr_size(const ax25_digi *);
void ax25_digi_invert(const ax25_digi *, ax25_digi *);
/* ax25_dev.c */
extern ax25_dev *ax25_dev_list;
extern spinlock_t ax25_dev_lock;
#if IS_ENABLED(CONFIG_AX25)
static inline ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
{
return dev->ax25_ptr;
}
#endif
ax25_dev *ax25_addr_ax25dev(ax25_address *);
void ax25_dev_device_up(struct net_device *);
void ax25_dev_device_down(struct net_device *);
int ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);
struct net_device *ax25_fwd_dev(struct net_device *);
void ax25_dev_free(void);
/* ax25_ds_in.c */
int ax25_ds_frame_in(ax25_cb *, struct sk_buff *, int);
/* ax25_ds_subr.c */
void ax25_ds_nr_error_recovery(ax25_cb *);
void ax25_ds_enquiry_response(ax25_cb *);
void ax25_ds_establish_data_link(ax25_cb *);
void ax25_dev_dama_off(ax25_dev *);
void ax25_dama_on(ax25_cb *);
void ax25_dama_off(ax25_cb *);
/* ax25_ds_timer.c */
void ax25_ds_setup_timer(ax25_dev *);
void ax25_ds_set_timer(ax25_dev *);
void ax25_ds_del_timer(ax25_dev *);
void ax25_ds_timer(ax25_cb *);
void ax25_ds_t1_timeout(ax25_cb *);
void ax25_ds_heartbeat_expiry(ax25_cb *);
void ax25_ds_t3timer_expiry(ax25_cb *);
void ax25_ds_idletimer_expiry(ax25_cb *);
/* ax25_iface.c */
struct ax25_protocol {
struct ax25_protocol *next;
unsigned int pid;
int (*func)(struct sk_buff *, ax25_cb *);
};
void ax25_register_pid(struct ax25_protocol *ap);
void ax25_protocol_release(unsigned int);
struct ax25_linkfail {
struct hlist_node lf_node;
void (*func)(ax25_cb *, int);
};
void ax25_linkfail_register(struct ax25_linkfail *lf);
void ax25_linkfail_release(struct ax25_linkfail *lf);
int __must_check ax25_listen_register(ax25_address *, struct net_device *);
void ax25_listen_release(ax25_address *, struct net_device *);
int(*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
int ax25_listen_mine(ax25_address *, struct net_device *);
void ax25_link_failed(ax25_cb *, int);
int ax25_protocol_is_registered(unsigned int);
/* ax25_in.c */
int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *,
struct net_device *);
/* ax25_ip.c */
netdev_tx_t ax25_ip_xmit(struct sk_buff *skb);
extern const struct header_ops ax25_header_ops;
/* ax25_out.c */
ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *,
ax25_digi *, struct net_device *);
void ax25_output(ax25_cb *, int, struct sk_buff *);
void ax25_kick(ax25_cb *);
void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev);
int ax25_check_iframes_acked(ax25_cb *, unsigned short);
/* ax25_route.c */
void ax25_rt_device_down(struct net_device *);
int ax25_rt_ioctl(unsigned int, void __user *);
extern const struct seq_operations ax25_rt_seqops;
ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);
int ax25_rt_autobind(ax25_cb *, ax25_address *);
struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *,
ax25_address *, ax25_digi *);
void ax25_rt_free(void);
/* ax25_std_in.c */
int ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);
/* ax25_std_subr.c */
void ax25_std_nr_error_recovery(ax25_cb *);
void ax25_std_establish_data_link(ax25_cb *);
void ax25_std_transmit_enquiry(ax25_cb *);
void ax25_std_enquiry_response(ax25_cb *);
void ax25_std_timeout_response(ax25_cb *);
/* ax25_std_timer.c */
void ax25_std_heartbeat_expiry(ax25_cb *);
void ax25_std_t1timer_expiry(ax25_cb *);
void ax25_std_t2timer_expiry(ax25_cb *);
void ax25_std_t3timer_expiry(ax25_cb *);
void ax25_std_idletimer_expiry(ax25_cb *);
/* ax25_subr.c */
void ax25_clear_queues(ax25_cb *);
void ax25_frames_acked(ax25_cb *, unsigned short);
void ax25_requeue_frames(ax25_cb *);
int ax25_validate_nr(ax25_cb *, unsigned short);
int ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
void ax25_send_control(ax25_cb *, int, int, int);
void ax25_return_dm(struct net_device *, ax25_address *, ax25_address *,
ax25_digi *);
void ax25_calculate_t1(ax25_cb *);
void ax25_calculate_rtt(ax25_cb *);
void ax25_disconnect(ax25_cb *, int);
/* ax25_timer.c */
void ax25_setup_timers(ax25_cb *);
void ax25_start_heartbeat(ax25_cb *);
void ax25_start_t1timer(ax25_cb *);
void ax25_start_t2timer(ax25_cb *);
void ax25_start_t3timer(ax25_cb *);
void ax25_start_idletimer(ax25_cb *);
void ax25_stop_heartbeat(ax25_cb *);
void ax25_stop_t1timer(ax25_cb *);
void ax25_stop_t2timer(ax25_cb *);
void ax25_stop_t3timer(ax25_cb *);
void ax25_stop_idletimer(ax25_cb *);
int ax25_t1timer_running(ax25_cb *);
unsigned long ax25_display_timer(struct timer_list *);
/* ax25_uid.c */
extern int ax25_uid_policy;
ax25_uid_assoc *ax25_findbyuid(kuid_t);
int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
extern const struct seq_operations ax25_uid_seqops;
void ax25_uid_free(void);
/* sysctl_net_ax25.c */
#ifdef CONFIG_SYSCTL
int ax25_register_dev_sysctl(ax25_dev *ax25_dev);
void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev);
#else
static inline int ax25_register_dev_sysctl(ax25_dev *ax25_dev) { return 0; }
static inline void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) {}
#endif /* CONFIG_SYSCTL */
#endif
+45
View File
@@ -0,0 +1,45 @@
/* include/net/ax88796.h
*
* Copyright 2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef __NET_AX88796_PLAT_H
#define __NET_AX88796_PLAT_H
struct sk_buff;
struct net_device;
struct platform_device;
#define AXFLG_HAS_EEPROM (1<<0)
#define AXFLG_MAC_FROMDEV (1<<1) /* device already has MAC */
#define AXFLG_HAS_93CX6 (1<<2) /* use eeprom_93cx6 driver */
#define AXFLG_MAC_FROMPLATFORM (1<<3) /* MAC given by platform data */
struct ax_plat_data {
unsigned int flags;
unsigned char wordlength; /* 1 or 2 */
unsigned char dcr_val; /* default value for DCR */
unsigned char rcr_val; /* default value for RCR */
unsigned char gpoc_val; /* default value for GPOC */
u32 *reg_offsets; /* register offsets */
u8 *mac_addr; /* MAC addr (only used when
AXFLG_MAC_FROMPLATFORM is used */
/* uses default ax88796 buffer if set to NULL */
void (*block_output)(struct net_device *dev, int count,
const unsigned char *buf, int star_page);
void (*block_input)(struct net_device *dev, int count,
struct sk_buff *skb, int ring_offset);
/* returns nonzero if a pending interrupt request might by caused by
* the ax88786. Handles all interrupts if set to NULL
*/
int (*check_irq)(struct platform_device *pdev);
};
#endif /* __NET_AX88796_PLAT_H */
+416
View File
@@ -0,0 +1,416 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __BLUETOOTH_H
#define __BLUETOOTH_H
#include <linux/poll.h>
#include <net/sock.h>
#include <linux/seq_file.h>
#define BT_SUBSYS_VERSION 2
#define BT_SUBSYS_REVISION 22
#ifndef AF_BLUETOOTH
#define AF_BLUETOOTH 31
#define PF_BLUETOOTH AF_BLUETOOTH
#endif
/* Bluetooth versions */
#define BLUETOOTH_VER_1_1 1
#define BLUETOOTH_VER_1_2 2
#define BLUETOOTH_VER_2_0 3
/* Reserv for core and drivers use */
#define BT_SKB_RESERVE 8
#define BTPROTO_L2CAP 0
#define BTPROTO_HCI 1
#define BTPROTO_SCO 2
#define BTPROTO_RFCOMM 3
#define BTPROTO_BNEP 4
#define BTPROTO_CMTP 5
#define BTPROTO_HIDP 6
#define BTPROTO_AVDTP 7
#define SOL_HCI 0
#define SOL_L2CAP 6
#define SOL_SCO 17
#define SOL_RFCOMM 18
#define BT_SECURITY 4
struct bt_security {
__u8 level;
__u8 key_size;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3
#define BT_SECURITY_FIPS 4
#define BT_DEFER_SETUP 7
#define BT_FLUSHABLE 8
#define BT_FLUSHABLE_OFF 0
#define BT_FLUSHABLE_ON 1
#define BT_POWER 9
struct bt_power {
__u8 force_active;
};
#define BT_POWER_FORCE_ACTIVE_OFF 0
#define BT_POWER_FORCE_ACTIVE_ON 1
#define BT_CHANNEL_POLICY 10
/* BR/EDR only (default policy)
* AMP controllers cannot be used.
* Channel move requests from the remote device are denied.
* If the L2CAP channel is currently using AMP, move the channel to BR/EDR.
*/
#define BT_CHANNEL_POLICY_BREDR_ONLY 0
/* BR/EDR Preferred
* Allow use of AMP controllers.
* If the L2CAP channel is currently on AMP, move it to BR/EDR.
* Channel move requests from the remote device are allowed.
*/
#define BT_CHANNEL_POLICY_BREDR_PREFERRED 1
/* AMP Preferred
* Allow use of AMP controllers
* If the L2CAP channel is currently on BR/EDR and AMP controller
* resources are available, initiate a channel move to AMP.
* Channel move requests from the remote device are allowed.
* If the L2CAP socket has not been connected yet, try to create
* and configure the channel directly on an AMP controller rather
* than BR/EDR.
*/
#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
#define BT_VOICE 11
struct bt_voice {
__u16 setting;
};
#define BT_VOICE_TRANSPARENT 0x0003
#define BT_VOICE_CVSD_16BIT 0x0060
#define BT_SNDMTU 12
#define BT_RCVMTU 13
__printf(1, 2)
void bt_info(const char *fmt, ...);
__printf(1, 2)
void bt_warn(const char *fmt, ...);
__printf(1, 2)
void bt_err(const char *fmt, ...);
__printf(1, 2)
void bt_err_ratelimited(const char *fmt, ...);
#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
#define BT_WARN(fmt, ...) bt_warn(fmt "\n", ##__VA_ARGS__)
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
#define BT_ERR_RATELIMITED(fmt, ...) bt_err_ratelimited(fmt "\n", ##__VA_ARGS__)
#define bt_dev_info(hdev, fmt, ...) \
BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_warn(hdev, fmt, ...) \
BT_WARN("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_err(hdev, fmt, ...) \
BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_dbg(hdev, fmt, ...) \
BT_DBG("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_err_ratelimited(hdev, fmt, ...) \
BT_ERR_RATELIMITED("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
/* Connection and socket states */
enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
/* If unused will be removed by compiler */
static inline const char *state_to_string(int state)
{
switch (state) {
case BT_CONNECTED:
return "BT_CONNECTED";
case BT_OPEN:
return "BT_OPEN";
case BT_BOUND:
return "BT_BOUND";
case BT_LISTEN:
return "BT_LISTEN";
case BT_CONNECT:
return "BT_CONNECT";
case BT_CONNECT2:
return "BT_CONNECT2";
case BT_CONFIG:
return "BT_CONFIG";
case BT_DISCONN:
return "BT_DISCONN";
case BT_CLOSED:
return "BT_CLOSED";
}
return "invalid state";
}
/* BD Address */
typedef struct {
__u8 b[6];
} __packed bdaddr_t;
/* BD Address type */
#define BDADDR_BREDR 0x00
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02
static inline bool bdaddr_type_is_valid(u8 type)
{
switch (type) {
case BDADDR_BREDR:
case BDADDR_LE_PUBLIC:
case BDADDR_LE_RANDOM:
return true;
}
return false;
}
static inline bool bdaddr_type_is_le(u8 type)
{
switch (type) {
case BDADDR_LE_PUBLIC:
case BDADDR_LE_RANDOM:
return true;
}
return false;
}
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_NONE (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
/* Copy, swap, convert BD Address */
static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
return memcmp(ba1, ba2, sizeof(bdaddr_t));
}
static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
{
memcpy(dst, src, sizeof(bdaddr_t));
}
void baswap(bdaddr_t *dst, const bdaddr_t *src);
/* Common socket structures and functions */
#define bt_sk(__sk) ((struct bt_sock *) __sk)
struct bt_sock {
struct sock sk;
struct list_head accept_q;
struct sock *parent;
unsigned long flags;
void (*skb_msg_name)(struct sk_buff *, void *, int *);
};
enum {
BT_SK_DEFER_SETUP,
BT_SK_SUSPEND,
};
struct bt_sock_list {
struct hlist_head head;
rwlock_t lock;
#ifdef CONFIG_PROC_FS
int (* custom_seq_show)(struct seq_file *, void *);
#endif
};
int bt_sock_register(int proto, const struct net_proto_family *ops);
void bt_sock_unregister(int proto);
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
int flags);
int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg,
size_t len, int flags);
__poll_t bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
int bt_sock_wait_ready(struct sock *sk, unsigned long flags);
void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh);
void bt_accept_unlink(struct sock *sk);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */
struct l2cap_ctrl {
u8 sframe:1,
poll:1,
final:1,
fcs:1,
sar:2,
super:2;
u16 reqseq;
u16 txseq;
u8 retries;
__le16 psm;
bdaddr_t bdaddr;
struct l2cap_chan *chan;
};
struct hci_dev;
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode);
typedef void (*hci_req_complete_skb_t)(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb);
#define HCI_REQ_START BIT(0)
#define HCI_REQ_SKB BIT(1)
struct hci_ctrl {
u16 opcode;
u8 req_flags;
u8 req_event;
union {
hci_req_complete_t req_complete;
hci_req_complete_skb_t req_complete_skb;
};
};
struct bt_skb_cb {
u8 pkt_type;
u8 force_active;
u16 expect;
u8 incoming:1;
union {
struct l2cap_ctrl l2cap;
struct hci_ctrl hci;
};
};
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
#define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type
#define hci_skb_expect(skb) bt_cb((skb))->expect
#define hci_skb_opcode(skb) bt_cb((skb))->hci.opcode
static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
{
struct sk_buff *skb;
skb = alloc_skb(len + BT_SKB_RESERVE, how);
if (skb)
skb_reserve(skb, BT_SKB_RESERVE);
return skb;
}
static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
unsigned long len, int nb, int *err)
{
struct sk_buff *skb;
skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err);
if (skb)
skb_reserve(skb, BT_SKB_RESERVE);
if (!skb && *err)
return NULL;
*err = sock_error(sk);
if (*err)
goto out;
if (sk->sk_shutdown) {
*err = -ECONNRESET;
goto out;
}
return skb;
out:
kfree_skb(skb);
return NULL;
}
int bt_to_errno(u16 code);
void hci_sock_set_flag(struct sock *sk, int nr);
void hci_sock_clear_flag(struct sock *sk, int nr);
int hci_sock_test_flag(struct sock *sk, int nr);
unsigned short hci_sock_get_channel(struct sock *sk);
u32 hci_sock_get_cookie(struct sock *sk);
int hci_sock_init(void);
void hci_sock_cleanup(void);
int bt_sysfs_init(void);
void bt_sysfs_cleanup(void);
int bt_procfs_init(struct net *net, const char *name,
struct bt_sock_list *sk_list,
int (*seq_show)(struct seq_file *, void *));
void bt_procfs_cleanup(struct net *net, const char *name);
extern struct dentry *bt_debugfs;
int l2cap_init(void);
void l2cap_exit(void);
#if IS_ENABLED(CONFIG_BT_BREDR)
int sco_init(void);
void sco_exit(void);
#else
static inline int sco_init(void)
{
return 0;
}
static inline void sco_exit(void)
{
}
#endif
int mgmt_init(void);
void mgmt_exit(void);
void bt_sock_reclassify_lock(struct sock *sk, int proto);
#endif /* __BLUETOOTH_H */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+67
View File
@@ -0,0 +1,67 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2011-2012 Intel Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __HCI_MON_H
#define __HCI_MON_H
struct hci_mon_hdr {
__le16 opcode;
__le16 index;
__le16 len;
} __packed;
#define HCI_MON_HDR_SIZE 6
#define HCI_MON_NEW_INDEX 0
#define HCI_MON_DEL_INDEX 1
#define HCI_MON_COMMAND_PKT 2
#define HCI_MON_EVENT_PKT 3
#define HCI_MON_ACL_TX_PKT 4
#define HCI_MON_ACL_RX_PKT 5
#define HCI_MON_SCO_TX_PKT 6
#define HCI_MON_SCO_RX_PKT 7
#define HCI_MON_OPEN_INDEX 8
#define HCI_MON_CLOSE_INDEX 9
#define HCI_MON_INDEX_INFO 10
#define HCI_MON_VENDOR_DIAG 11
#define HCI_MON_SYSTEM_NOTE 12
#define HCI_MON_USER_LOGGING 13
#define HCI_MON_CTRL_OPEN 14
#define HCI_MON_CTRL_CLOSE 15
#define HCI_MON_CTRL_COMMAND 16
#define HCI_MON_CTRL_EVENT 17
struct hci_mon_new_index {
__u8 type;
__u8 bus;
bdaddr_t bdaddr;
char name[8];
} __packed;
#define HCI_MON_NEW_INDEX_SIZE 16
struct hci_mon_index_info {
bdaddr_t bdaddr;
__le16 manufacturer;
} __packed;
#define HCI_MON_INDEX_INFO_SIZE 8
#endif /* __HCI_MON_H */
+176
View File
@@ -0,0 +1,176 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __HCI_SOCK_H
#define __HCI_SOCK_H
/* Socket options */
#define HCI_DATA_DIR 1
#define HCI_FILTER 2
#define HCI_TIME_STAMP 3
/* CMSG flags */
#define HCI_CMSG_DIR 0x0001
#define HCI_CMSG_TSTAMP 0x0002
struct sockaddr_hci {
sa_family_t hci_family;
unsigned short hci_dev;
unsigned short hci_channel;
};
#define HCI_DEV_NONE 0xffff
#define HCI_CHANNEL_RAW 0
#define HCI_CHANNEL_USER 1
#define HCI_CHANNEL_MONITOR 2
#define HCI_CHANNEL_CONTROL 3
#define HCI_CHANNEL_LOGGING 4
struct hci_filter {
unsigned long type_mask;
unsigned long event_mask[2];
__le16 opcode;
};
struct hci_ufilter {
__u32 type_mask;
__u32 event_mask[2];
__le16 opcode;
};
#define HCI_FLT_TYPE_BITS 31
#define HCI_FLT_EVENT_BITS 63
#define HCI_FLT_OGF_BITS 63
#define HCI_FLT_OCF_BITS 127
/* Ioctl defines */
#define HCIDEVUP _IOW('H', 201, int)
#define HCIDEVDOWN _IOW('H', 202, int)
#define HCIDEVRESET _IOW('H', 203, int)
#define HCIDEVRESTAT _IOW('H', 204, int)
#define HCIGETDEVLIST _IOR('H', 210, int)
#define HCIGETDEVINFO _IOR('H', 211, int)
#define HCIGETCONNLIST _IOR('H', 212, int)
#define HCIGETCONNINFO _IOR('H', 213, int)
#define HCIGETAUTHINFO _IOR('H', 215, int)
#define HCISETRAW _IOW('H', 220, int)
#define HCISETSCAN _IOW('H', 221, int)
#define HCISETAUTH _IOW('H', 222, int)
#define HCISETENCRYPT _IOW('H', 223, int)
#define HCISETPTYPE _IOW('H', 224, int)
#define HCISETLINKPOL _IOW('H', 225, int)
#define HCISETLINKMODE _IOW('H', 226, int)
#define HCISETACLMTU _IOW('H', 227, int)
#define HCISETSCOMTU _IOW('H', 228, int)
#define HCIBLOCKADDR _IOW('H', 230, int)
#define HCIUNBLOCKADDR _IOW('H', 231, int)
#define HCIINQUIRY _IOR('H', 240, int)
/* Ioctl requests structures */
struct hci_dev_stats {
__u32 err_rx;
__u32 err_tx;
__u32 cmd_tx;
__u32 evt_rx;
__u32 acl_tx;
__u32 acl_rx;
__u32 sco_tx;
__u32 sco_rx;
__u32 byte_rx;
__u32 byte_tx;
};
struct hci_dev_info {
__u16 dev_id;
char name[8];
bdaddr_t bdaddr;
__u32 flags;
__u8 type;
__u8 features[8];
__u32 pkt_type;
__u32 link_policy;
__u32 link_mode;
__u16 acl_mtu;
__u16 acl_pkts;
__u16 sco_mtu;
__u16 sco_pkts;
struct hci_dev_stats stat;
};
struct hci_conn_info {
__u16 handle;
bdaddr_t bdaddr;
__u8 type;
__u8 out;
__u16 state;
__u32 link_mode;
};
struct hci_dev_req {
__u16 dev_id;
__u32 dev_opt;
};
struct hci_dev_list_req {
__u16 dev_num;
struct hci_dev_req dev_req[0]; /* hci_dev_req structures */
};
struct hci_conn_list_req {
__u16 dev_id;
__u16 conn_num;
struct hci_conn_info conn_info[0];
};
struct hci_conn_info_req {
bdaddr_t bdaddr;
__u8 type;
struct hci_conn_info conn_info[0];
};
struct hci_auth_info_req {
bdaddr_t bdaddr;
__u8 type;
};
struct hci_inquiry_req {
__u16 dev_id;
__u16 flags;
__u8 lap[3];
__u8 length;
__u8 num_rsp;
};
#define IREQ_CACHE_FLUSH 0x0001
#endif /* __HCI_SOCK_H */
+953
View File
@@ -0,0 +1,953 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __L2CAP_H
#define __L2CAP_H
#include <asm/unaligned.h>
#include <linux/atomic.h>
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_MIN_MTU 48
#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
#define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF
#define L2CAP_DEFAULT_TX_WINDOW 63
#define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF
#define L2CAP_DEFAULT_MAX_TX 3
#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1492 /* Sized for AMP packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF
#define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF
#define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF
#define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */
#define L2CAP_LE_MIN_MTU 23
#define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100)
#define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000)
#define L2CAP_ENC_TIMEOUT msecs_to_jiffies(5000)
#define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000)
#define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000)
#define L2CAP_MOVE_TIMEOUT msecs_to_jiffies(4000)
#define L2CAP_MOVE_ERTX_TIMEOUT msecs_to_jiffies(60000)
#define L2CAP_WAIT_ACK_POLL_PERIOD msecs_to_jiffies(200)
#define L2CAP_WAIT_ACK_TIMEOUT msecs_to_jiffies(10000)
#define L2CAP_A2MP_DEFAULT_MTU 670
/* L2CAP socket address */
struct sockaddr_l2 {
sa_family_t l2_family;
__le16 l2_psm;
bdaddr_t l2_bdaddr;
__le16 l2_cid;
__u8 l2_bdaddr_type;
};
/* L2CAP socket options */
#define L2CAP_OPTIONS 0x01
struct l2cap_options {
__u16 omtu;
__u16 imtu;
__u16 flush_to;
__u8 mode;
__u8 fcs;
__u8 max_tx;
__u16 txwin_size;
};
#define L2CAP_CONNINFO 0x02
struct l2cap_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define L2CAP_LM 0x03
#define L2CAP_LM_MASTER 0x0001
#define L2CAP_LM_AUTH 0x0002
#define L2CAP_LM_ENCRYPT 0x0004
#define L2CAP_LM_TRUSTED 0x0008
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
#define L2CAP_LM_FIPS 0x0040
/* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02
#define L2CAP_CONN_RSP 0x03
#define L2CAP_CONF_REQ 0x04
#define L2CAP_CONF_RSP 0x05
#define L2CAP_DISCONN_REQ 0x06
#define L2CAP_DISCONN_RSP 0x07
#define L2CAP_ECHO_REQ 0x08
#define L2CAP_ECHO_RSP 0x09
#define L2CAP_INFO_REQ 0x0a
#define L2CAP_INFO_RSP 0x0b
#define L2CAP_CREATE_CHAN_REQ 0x0c
#define L2CAP_CREATE_CHAN_RSP 0x0d
#define L2CAP_MOVE_CHAN_REQ 0x0e
#define L2CAP_MOVE_CHAN_RSP 0x0f
#define L2CAP_MOVE_CHAN_CFM 0x10
#define L2CAP_MOVE_CHAN_CFM_RSP 0x11
#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
#define L2CAP_LE_CONN_REQ 0x14
#define L2CAP_LE_CONN_RSP 0x15
#define L2CAP_LE_CREDITS 0x16
/* L2CAP extended feature mask */
#define L2CAP_FEAT_FLOWCTL 0x00000001
#define L2CAP_FEAT_RETRANS 0x00000002
#define L2CAP_FEAT_BIDIR_QOS 0x00000004
#define L2CAP_FEAT_ERTM 0x00000008
#define L2CAP_FEAT_STREAMING 0x00000010
#define L2CAP_FEAT_FCS 0x00000020
#define L2CAP_FEAT_EXT_FLOW 0x00000040
#define L2CAP_FEAT_FIXED_CHAN 0x00000080
#define L2CAP_FEAT_EXT_WINDOW 0x00000100
#define L2CAP_FEAT_UCD 0x00000200
/* L2CAP checksum option */
#define L2CAP_FCS_NONE 0x00
#define L2CAP_FCS_CRC16 0x01
/* L2CAP fixed channels */
#define L2CAP_FC_SIG_BREDR 0x02
#define L2CAP_FC_CONNLESS 0x04
#define L2CAP_FC_A2MP 0x08
#define L2CAP_FC_ATT 0x10
#define L2CAP_FC_SIG_LE 0x20
#define L2CAP_FC_SMP_LE 0x40
#define L2CAP_FC_SMP_BREDR 0x80
/* L2CAP Control Field bit masks */
#define L2CAP_CTRL_SAR 0xC000
#define L2CAP_CTRL_REQSEQ 0x3F00
#define L2CAP_CTRL_TXSEQ 0x007E
#define L2CAP_CTRL_SUPERVISE 0x000C
#define L2CAP_CTRL_RETRANS 0x0080
#define L2CAP_CTRL_FINAL 0x0080
#define L2CAP_CTRL_POLL 0x0010
#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
#define L2CAP_CTRL_TXSEQ_SHIFT 1
#define L2CAP_CTRL_SUPER_SHIFT 2
#define L2CAP_CTRL_POLL_SHIFT 4
#define L2CAP_CTRL_FINAL_SHIFT 7
#define L2CAP_CTRL_REQSEQ_SHIFT 8
#define L2CAP_CTRL_SAR_SHIFT 14
/* L2CAP Extended Control Field bit mask */
#define L2CAP_EXT_CTRL_TXSEQ 0xFFFC0000
#define L2CAP_EXT_CTRL_SAR 0x00030000
#define L2CAP_EXT_CTRL_SUPERVISE 0x00030000
#define L2CAP_EXT_CTRL_REQSEQ 0x0000FFFC
#define L2CAP_EXT_CTRL_POLL 0x00040000
#define L2CAP_EXT_CTRL_FINAL 0x00000002
#define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */
#define L2CAP_EXT_CTRL_FINAL_SHIFT 1
#define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2
#define L2CAP_EXT_CTRL_SAR_SHIFT 16
#define L2CAP_EXT_CTRL_SUPER_SHIFT 16
#define L2CAP_EXT_CTRL_POLL_SHIFT 18
#define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18
/* L2CAP Supervisory Function */
#define L2CAP_SUPER_RR 0x00
#define L2CAP_SUPER_REJ 0x01
#define L2CAP_SUPER_RNR 0x02
#define L2CAP_SUPER_SREJ 0x03
/* L2CAP Segmentation and Reassembly */
#define L2CAP_SAR_UNSEGMENTED 0x00
#define L2CAP_SAR_START 0x01
#define L2CAP_SAR_END 0x02
#define L2CAP_SAR_CONTINUE 0x03
/* L2CAP Command rej. reasons */
#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
#define L2CAP_REJ_MTU_EXCEEDED 0x0001
#define L2CAP_REJ_INVALID_CID 0x0002
/* L2CAP structures */
struct l2cap_hdr {
__le16 len;
__le16 cid;
} __packed;
#define L2CAP_HDR_SIZE 4
#define L2CAP_ENH_HDR_SIZE 6
#define L2CAP_EXT_HDR_SIZE 8
#define L2CAP_FCS_SIZE 2
#define L2CAP_SDULEN_SIZE 2
#define L2CAP_PSMLEN_SIZE 2
#define L2CAP_ENH_CTRL_SIZE 2
#define L2CAP_EXT_CTRL_SIZE 4
struct l2cap_cmd_hdr {
__u8 code;
__u8 ident;
__le16 len;
} __packed;
#define L2CAP_CMD_HDR_SIZE 4
struct l2cap_cmd_rej_unk {
__le16 reason;
} __packed;
struct l2cap_cmd_rej_mtu {
__le16 reason;
__le16 max_mtu;
} __packed;
struct l2cap_cmd_rej_cid {
__le16 reason;
__le16 scid;
__le16 dcid;
} __packed;
struct l2cap_conn_req {
__le16 psm;
__le16 scid;
} __packed;
struct l2cap_conn_rsp {
__le16 dcid;
__le16 scid;
__le16 result;
__le16 status;
} __packed;
/* protocol/service multiplexer (PSM) */
#define L2CAP_PSM_SDP 0x0001
#define L2CAP_PSM_RFCOMM 0x0003
#define L2CAP_PSM_3DSP 0x0021
#define L2CAP_PSM_IPSP 0x0023 /* 6LoWPAN */
#define L2CAP_PSM_DYN_START 0x1001
#define L2CAP_PSM_DYN_END 0xffff
#define L2CAP_PSM_AUTO_END 0x10ff
#define L2CAP_PSM_LE_DYN_START 0x0080
#define L2CAP_PSM_LE_DYN_END 0x00ff
/* channel identifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
#define L2CAP_CID_A2MP 0x0003
#define L2CAP_CID_ATT 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
#define L2CAP_CID_SMP_BREDR 0x0007
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
#define L2CAP_CID_LE_DYN_END 0x007f
/* connect/create channel results */
#define L2CAP_CR_SUCCESS 0x0000
#define L2CAP_CR_PEND 0x0001
#define L2CAP_CR_BAD_PSM 0x0002
#define L2CAP_CR_SEC_BLOCK 0x0003
#define L2CAP_CR_NO_MEM 0x0004
#define L2CAP_CR_BAD_AMP 0x0005
#define L2CAP_CR_AUTHENTICATION 0x0005
#define L2CAP_CR_AUTHORIZATION 0x0006
#define L2CAP_CR_BAD_KEY_SIZE 0x0007
#define L2CAP_CR_ENCRYPTION 0x0008
#define L2CAP_CR_INVALID_SCID 0x0009
#define L2CAP_CR_SCID_IN_USE 0x000A
/* connect/create channel status */
#define L2CAP_CS_NO_INFO 0x0000
#define L2CAP_CS_AUTHEN_PEND 0x0001
#define L2CAP_CS_AUTHOR_PEND 0x0002
struct l2cap_conf_req {
__le16 dcid;
__le16 flags;
__u8 data[0];
} __packed;
struct l2cap_conf_rsp {
__le16 scid;
__le16 flags;
__le16 result;
__u8 data[0];
} __packed;
#define L2CAP_CONF_SUCCESS 0x0000
#define L2CAP_CONF_UNACCEPT 0x0001
#define L2CAP_CONF_REJECT 0x0002
#define L2CAP_CONF_UNKNOWN 0x0003
#define L2CAP_CONF_PENDING 0x0004
#define L2CAP_CONF_EFS_REJECT 0x0005
/* configuration req/rsp continuation flag */
#define L2CAP_CONF_FLAG_CONTINUATION 0x0001
struct l2cap_conf_opt {
__u8 type;
__u8 len;
__u8 val[0];
} __packed;
#define L2CAP_CONF_OPT_SIZE 2
#define L2CAP_CONF_HINT 0x80
#define L2CAP_CONF_MASK 0x7f
#define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_FCS 0x05
#define L2CAP_CONF_EFS 0x06
#define L2CAP_CONF_EWS 0x07
#define L2CAP_CONF_MAX_SIZE 22
struct l2cap_conf_rfc {
__u8 mode;
__u8 txwin_size;
__u8 max_transmit;
__le16 retrans_timeout;
__le16 monitor_timeout;
__le16 max_pdu_size;
} __packed;
#define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01
#define L2CAP_MODE_FLOWCTL 0x02
#define L2CAP_MODE_ERTM 0x03
#define L2CAP_MODE_STREAMING 0x04
/* Unlike the above this one doesn't actually map to anything that would
* ever be sent over the air. Therefore, use a value that's unlikely to
* ever be used in the BR/EDR configuration phase.
*/
#define L2CAP_MODE_LE_FLOWCTL 0x80
struct l2cap_conf_efs {
__u8 id;
__u8 stype;
__le16 msdu;
__le32 sdu_itime;
__le32 acc_lat;
__le32 flush_to;
} __packed;
#define L2CAP_SERV_NOTRAFIC 0x00
#define L2CAP_SERV_BESTEFFORT 0x01
#define L2CAP_SERV_GUARANTEED 0x02
#define L2CAP_BESTEFFORT_ID 0x01
struct l2cap_disconn_req {
__le16 dcid;
__le16 scid;
} __packed;
struct l2cap_disconn_rsp {
__le16 dcid;
__le16 scid;
} __packed;
struct l2cap_info_req {
__le16 type;
} __packed;
struct l2cap_info_rsp {
__le16 type;
__le16 result;
__u8 data[0];
} __packed;
struct l2cap_create_chan_req {
__le16 psm;
__le16 scid;
__u8 amp_id;
} __packed;
struct l2cap_create_chan_rsp {
__le16 dcid;
__le16 scid;
__le16 result;
__le16 status;
} __packed;
struct l2cap_move_chan_req {
__le16 icid;
__u8 dest_amp_id;
} __packed;
struct l2cap_move_chan_rsp {
__le16 icid;
__le16 result;
} __packed;
#define L2CAP_MR_SUCCESS 0x0000
#define L2CAP_MR_PEND 0x0001
#define L2CAP_MR_BAD_ID 0x0002
#define L2CAP_MR_SAME_ID 0x0003
#define L2CAP_MR_NOT_SUPP 0x0004
#define L2CAP_MR_COLLISION 0x0005
#define L2CAP_MR_NOT_ALLOWED 0x0006
struct l2cap_move_chan_cfm {
__le16 icid;
__le16 result;
} __packed;
#define L2CAP_MC_CONFIRMED 0x0000
#define L2CAP_MC_UNCONFIRMED 0x0001
struct l2cap_move_chan_cfm_rsp {
__le16 icid;
} __packed;
/* info type */
#define L2CAP_IT_CL_MTU 0x0001
#define L2CAP_IT_FEAT_MASK 0x0002
#define L2CAP_IT_FIXED_CHAN 0x0003
/* info result */
#define L2CAP_IR_SUCCESS 0x0000
#define L2CAP_IR_NOTSUPP 0x0001
struct l2cap_conn_param_update_req {
__le16 min;
__le16 max;
__le16 latency;
__le16 to_multiplier;
} __packed;
struct l2cap_conn_param_update_rsp {
__le16 result;
} __packed;
/* Connection Parameters result */
#define L2CAP_CONN_PARAM_ACCEPTED 0x0000
#define L2CAP_CONN_PARAM_REJECTED 0x0001
#define L2CAP_LE_MAX_CREDITS 10
#define L2CAP_LE_DEFAULT_MPS 230
struct l2cap_le_conn_req {
__le16 psm;
__le16 scid;
__le16 mtu;
__le16 mps;
__le16 credits;
} __packed;
struct l2cap_le_conn_rsp {
__le16 dcid;
__le16 mtu;
__le16 mps;
__le16 credits;
__le16 result;
} __packed;
struct l2cap_le_credits {
__le16 cid;
__le16 credits;
} __packed;
/* ----- L2CAP channels and connections ----- */
struct l2cap_seq_list {
__u16 head;
__u16 tail;
__u16 mask;
__u16 *list;
};
#define L2CAP_SEQ_LIST_CLEAR 0xFFFF
#define L2CAP_SEQ_LIST_TAIL 0x8000
struct l2cap_chan {
struct l2cap_conn *conn;
struct hci_conn *hs_hcon;
struct hci_chan *hs_hchan;
struct kref kref;
atomic_t nesting;
__u8 state;
bdaddr_t dst;
__u8 dst_type;
bdaddr_t src;
__u8 src_type;
__le16 psm;
__le16 sport;
__u16 dcid;
__u16 scid;
__u16 imtu;
__u16 omtu;
__u16 flush_to;
__u8 mode;
__u8 chan_type;
__u8 chan_policy;
__u8 sec_level;
__u8 ident;
__u8 conf_req[64];
__u8 conf_len;
__u8 num_conf_req;
__u8 num_conf_rsp;
__u8 fcs;
__u16 tx_win;
__u16 tx_win_max;
__u16 ack_win;
__u8 max_tx;
__u16 retrans_timeout;
__u16 monitor_timeout;
__u16 mps;
__u16 tx_credits;
__u16 rx_credits;
__u8 tx_state;
__u8 rx_state;
unsigned long conf_state;
unsigned long conn_state;
unsigned long flags;
__u8 remote_amp_id;
__u8 local_amp_id;
__u8 move_id;
__u8 move_state;
__u8 move_role;
__u16 next_tx_seq;
__u16 expected_ack_seq;
__u16 expected_tx_seq;
__u16 buffer_seq;
__u16 srej_save_reqseq;
__u16 last_acked_seq;
__u16 frames_sent;
__u16 unacked_frames;
__u8 retry_count;
__u16 sdu_len;
struct sk_buff *sdu;
struct sk_buff *sdu_last_frag;
__u16 remote_tx_win;
__u8 remote_max_tx;
__u16 remote_mps;
__u8 local_id;
__u8 local_stype;
__u16 local_msdu;
__u32 local_sdu_itime;
__u32 local_acc_lat;
__u32 local_flush_to;
__u8 remote_id;
__u8 remote_stype;
__u16 remote_msdu;
__u32 remote_sdu_itime;
__u32 remote_acc_lat;
__u32 remote_flush_to;
struct delayed_work chan_timer;
struct delayed_work retrans_timer;
struct delayed_work monitor_timer;
struct delayed_work ack_timer;
struct sk_buff *tx_send_head;
struct sk_buff_head tx_q;
struct sk_buff_head srej_q;
struct l2cap_seq_list srej_list;
struct l2cap_seq_list retrans_list;
struct list_head list;
struct list_head global_l;
void *data;
const struct l2cap_ops *ops;
struct mutex lock;
};
struct l2cap_ops {
char *name;
struct l2cap_chan *(*new_connection) (struct l2cap_chan *chan);
int (*recv) (struct l2cap_chan * chan,
struct sk_buff *skb);
void (*teardown) (struct l2cap_chan *chan, int err);
void (*close) (struct l2cap_chan *chan);
void (*state_change) (struct l2cap_chan *chan,
int state, int err);
void (*ready) (struct l2cap_chan *chan);
void (*defer) (struct l2cap_chan *chan);
void (*resume) (struct l2cap_chan *chan);
void (*suspend) (struct l2cap_chan *chan);
void (*set_shutdown) (struct l2cap_chan *chan);
long (*get_sndtimeo) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb);
int (*filter) (struct l2cap_chan * chan,
struct sk_buff *skb);
};
struct l2cap_conn {
struct hci_conn *hcon;
struct hci_chan *hchan;
unsigned int mtu;
__u32 feat_mask;
__u8 remote_fixed_chan;
__u8 local_fixed_chan;
__u8 info_state;
__u8 info_ident;
struct delayed_work info_timer;
struct sk_buff *rx_skb;
__u32 rx_len;
__u8 tx_ident;
struct mutex ident_lock;
struct sk_buff_head pending_rx;
struct work_struct pending_rx_work;
struct work_struct id_addr_update_work;
__u8 disc_reason;
struct l2cap_chan *smp;
struct list_head chan_l;
struct mutex chan_lock;
struct kref ref;
struct list_head users;
};
struct l2cap_user {
struct list_head list;
int (*probe) (struct l2cap_conn *conn, struct l2cap_user *user);
void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user);
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
#define L2CAP_CHAN_RAW 1
#define L2CAP_CHAN_CONN_LESS 2
#define L2CAP_CHAN_CONN_ORIENTED 3
#define L2CAP_CHAN_FIXED 4
/* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
struct l2cap_pinfo {
struct bt_sock bt;
struct l2cap_chan *chan;
struct sk_buff *rx_busy_skb;
};
enum {
CONF_REQ_SENT,
CONF_INPUT_DONE,
CONF_OUTPUT_DONE,
CONF_MTU_DONE,
CONF_MODE_DONE,
CONF_CONNECT_PEND,
CONF_RECV_NO_FCS,
CONF_STATE2_DEVICE,
CONF_EWS_RECV,
CONF_LOC_CONF_PEND,
CONF_REM_CONF_PEND,
CONF_NOT_COMPLETE,
};
#define L2CAP_CONF_MAX_CONF_REQ 2
#define L2CAP_CONF_MAX_CONF_RSP 2
enum {
CONN_SREJ_SENT,
CONN_WAIT_F,
CONN_SREJ_ACT,
CONN_SEND_PBIT,
CONN_REMOTE_BUSY,
CONN_LOCAL_BUSY,
CONN_REJ_ACT,
CONN_SEND_FBIT,
CONN_RNR_SENT,
};
/* Definitions for flags in l2cap_chan */
enum {
FLAG_ROLE_SWITCH,
FLAG_FORCE_ACTIVE,
FLAG_FORCE_RELIABLE,
FLAG_FLUSHABLE,
FLAG_EXT_CTRL,
FLAG_EFS_ENABLE,
FLAG_DEFER_SETUP,
FLAG_LE_CONN_REQ_SENT,
FLAG_PENDING_SECURITY,
FLAG_HOLD_HCI_CONN,
};
/* Lock nesting levels for L2CAP channels. We need these because lockdep
* otherwise considers all channels equal and will e.g. complain about a
* connection oriented channel triggering SMP procedures or a listening
* channel creating and locking a child channel.
*/
enum {
L2CAP_NESTING_SMP,
L2CAP_NESTING_NORMAL,
L2CAP_NESTING_PARENT,
};
enum {
L2CAP_TX_STATE_XMIT,
L2CAP_TX_STATE_WAIT_F,
};
enum {
L2CAP_RX_STATE_RECV,
L2CAP_RX_STATE_SREJ_SENT,
L2CAP_RX_STATE_MOVE,
L2CAP_RX_STATE_WAIT_P,
L2CAP_RX_STATE_WAIT_F,
};
enum {
L2CAP_TXSEQ_EXPECTED,
L2CAP_TXSEQ_EXPECTED_SREJ,
L2CAP_TXSEQ_UNEXPECTED,
L2CAP_TXSEQ_UNEXPECTED_SREJ,
L2CAP_TXSEQ_DUPLICATE,
L2CAP_TXSEQ_DUPLICATE_SREJ,
L2CAP_TXSEQ_INVALID,
L2CAP_TXSEQ_INVALID_IGNORE,
};
enum {
L2CAP_EV_DATA_REQUEST,
L2CAP_EV_LOCAL_BUSY_DETECTED,
L2CAP_EV_LOCAL_BUSY_CLEAR,
L2CAP_EV_RECV_REQSEQ_AND_FBIT,
L2CAP_EV_RECV_FBIT,
L2CAP_EV_RETRANS_TO,
L2CAP_EV_MONITOR_TO,
L2CAP_EV_EXPLICIT_POLL,
L2CAP_EV_RECV_IFRAME,
L2CAP_EV_RECV_RR,
L2CAP_EV_RECV_REJ,
L2CAP_EV_RECV_RNR,
L2CAP_EV_RECV_SREJ,
L2CAP_EV_RECV_FRAME,
};
enum {
L2CAP_MOVE_ROLE_NONE,
L2CAP_MOVE_ROLE_INITIATOR,
L2CAP_MOVE_ROLE_RESPONDER,
};
enum {
L2CAP_MOVE_STABLE,
L2CAP_MOVE_WAIT_REQ,
L2CAP_MOVE_WAIT_RSP,
L2CAP_MOVE_WAIT_RSP_SUCCESS,
L2CAP_MOVE_WAIT_CONFIRM,
L2CAP_MOVE_WAIT_CONFIRM_RSP,
L2CAP_MOVE_WAIT_LOGICAL_COMP,
L2CAP_MOVE_WAIT_LOGICAL_CFM,
L2CAP_MOVE_WAIT_LOCAL_BUSY,
L2CAP_MOVE_WAIT_PREPARE,
};
void l2cap_chan_hold(struct l2cap_chan *c);
void l2cap_chan_put(struct l2cap_chan *c);
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
{
mutex_lock_nested(&chan->lock, atomic_read(&chan->nesting));
}
static inline void l2cap_chan_unlock(struct l2cap_chan *chan)
{
mutex_unlock(&chan->lock);
}
static inline void l2cap_set_timer(struct l2cap_chan *chan,
struct delayed_work *work, long timeout)
{
BT_DBG("chan %p state %s timeout %ld", chan,
state_to_string(chan->state), timeout);
/* If delayed work cancelled do not hold(chan)
since it is already done with previous set_timer */
if (!cancel_delayed_work(work))
l2cap_chan_hold(chan);
schedule_delayed_work(work, timeout);
}
static inline bool l2cap_clear_timer(struct l2cap_chan *chan,
struct delayed_work *work)
{
bool ret;
/* put(chan) if delayed work cancelled otherwise it
is done in delayed work function */
ret = cancel_delayed_work(work);
if (ret)
l2cap_chan_put(chan);
return ret;
}
#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
{
if (seq1 >= seq2)
return seq1 - seq2;
else
return chan->tx_win_max + 1 - seq2 + seq1;
}
static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
{
return (seq + 1) % (chan->tx_win_max + 1);
}
static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
{
return NULL;
}
static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
{
return -ENOSYS;
}
static inline struct sk_buff *l2cap_chan_no_alloc_skb(struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb)
{
return ERR_PTR(-ENOSYS);
}
static inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err)
{
}
static inline void l2cap_chan_no_close(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_state_change(struct l2cap_chan *chan,
int state, int err)
{
}
static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_suspend(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_set_shutdown(struct l2cap_chan *chan)
{
}
static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
{
return 0;
}
extern bool disable_ertm;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
bool l2cap_is_socket(struct socket *sock);
void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan);
void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
struct l2cap_chan *l2cap_chan_create(void);
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
bdaddr_t *dst, u8 dst_type);
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
void l2cap_send_conn_req(struct l2cap_chan *chan);
void l2cap_move_start(struct l2cap_chan *chan);
void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
u8 status);
void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn);
void l2cap_conn_put(struct l2cap_conn *conn);
int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user);
void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user);
#endif /* __L2CAP_H */
+881
View File
@@ -0,0 +1,881 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2010 Nokia Corporation
Copyright (C) 2011-2012 Intel Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#define MGMT_INDEX_NONE 0xFFFF
#define MGMT_STATUS_SUCCESS 0x00
#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
#define MGMT_STATUS_NOT_CONNECTED 0x02
#define MGMT_STATUS_FAILED 0x03
#define MGMT_STATUS_CONNECT_FAILED 0x04
#define MGMT_STATUS_AUTH_FAILED 0x05
#define MGMT_STATUS_NOT_PAIRED 0x06
#define MGMT_STATUS_NO_RESOURCES 0x07
#define MGMT_STATUS_TIMEOUT 0x08
#define MGMT_STATUS_ALREADY_CONNECTED 0x09
#define MGMT_STATUS_BUSY 0x0a
#define MGMT_STATUS_REJECTED 0x0b
#define MGMT_STATUS_NOT_SUPPORTED 0x0c
#define MGMT_STATUS_INVALID_PARAMS 0x0d
#define MGMT_STATUS_DISCONNECTED 0x0e
#define MGMT_STATUS_NOT_POWERED 0x0f
#define MGMT_STATUS_CANCELLED 0x10
#define MGMT_STATUS_INVALID_INDEX 0x11
#define MGMT_STATUS_RFKILLED 0x12
#define MGMT_STATUS_ALREADY_PAIRED 0x13
#define MGMT_STATUS_PERMISSION_DENIED 0x14
struct mgmt_hdr {
__le16 opcode;
__le16 index;
__le16 len;
} __packed;
struct mgmt_addr_info {
bdaddr_t bdaddr;
__u8 type;
} __packed;
#define MGMT_ADDR_INFO_SIZE 7
#define MGMT_OP_READ_VERSION 0x0001
#define MGMT_READ_VERSION_SIZE 0
struct mgmt_rp_read_version {
__u8 version;
__le16 revision;
} __packed;
#define MGMT_OP_READ_COMMANDS 0x0002
#define MGMT_READ_COMMANDS_SIZE 0
struct mgmt_rp_read_commands {
__le16 num_commands;
__le16 num_events;
__le16 opcodes[0];
} __packed;
#define MGMT_OP_READ_INDEX_LIST 0x0003
#define MGMT_READ_INDEX_LIST_SIZE 0
struct mgmt_rp_read_index_list {
__le16 num_controllers;
__le16 index[0];
} __packed;
/* Reserve one extra byte for names in management messages so that they
* are always guaranteed to be nul-terminated */
#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
#define MGMT_MAX_SHORT_NAME_LENGTH (HCI_MAX_SHORT_NAME_LENGTH + 1)
#define MGMT_SETTING_POWERED 0x00000001
#define MGMT_SETTING_CONNECTABLE 0x00000002
#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004
#define MGMT_SETTING_DISCOVERABLE 0x00000008
#define MGMT_SETTING_BONDABLE 0x00000010
#define MGMT_SETTING_LINK_SECURITY 0x00000020
#define MGMT_SETTING_SSP 0x00000040
#define MGMT_SETTING_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
#define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_SETTING_SECURE_CONN 0x00000800
#define MGMT_SETTING_DEBUG_KEYS 0x00001000
#define MGMT_SETTING_PRIVACY 0x00002000
#define MGMT_SETTING_CONFIGURATION 0x00004000
#define MGMT_SETTING_STATIC_ADDRESS 0x00008000
#define MGMT_SETTING_PHY_CONFIGURATION 0x00010000
#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
struct mgmt_rp_read_info {
bdaddr_t bdaddr;
__u8 version;
__le16 manufacturer;
__le32 supported_settings;
__le32 current_settings;
__u8 dev_class[3];
__u8 name[MGMT_MAX_NAME_LENGTH];
__u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
struct mgmt_mode {
__u8 val;
} __packed;
#define MGMT_SETTING_SIZE 1
#define MGMT_OP_SET_POWERED 0x0005
#define MGMT_OP_SET_DISCOVERABLE 0x0006
struct mgmt_cp_set_discoverable {
__u8 val;
__le16 timeout;
} __packed;
#define MGMT_SET_DISCOVERABLE_SIZE 3
#define MGMT_OP_SET_CONNECTABLE 0x0007
#define MGMT_OP_SET_FAST_CONNECTABLE 0x0008
#define MGMT_OP_SET_BONDABLE 0x0009
#define MGMT_OP_SET_LINK_SECURITY 0x000A
#define MGMT_OP_SET_SSP 0x000B
#define MGMT_OP_SET_HS 0x000C
#define MGMT_OP_SET_LE 0x000D
#define MGMT_OP_SET_DEV_CLASS 0x000E
struct mgmt_cp_set_dev_class {
__u8 major;
__u8 minor;
} __packed;
#define MGMT_SET_DEV_CLASS_SIZE 2
#define MGMT_OP_SET_LOCAL_NAME 0x000F
struct mgmt_cp_set_local_name {
__u8 name[MGMT_MAX_NAME_LENGTH];
__u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
#define MGMT_SET_LOCAL_NAME_SIZE 260
#define MGMT_OP_ADD_UUID 0x0010
struct mgmt_cp_add_uuid {
__u8 uuid[16];
__u8 svc_hint;
} __packed;
#define MGMT_ADD_UUID_SIZE 17
#define MGMT_OP_REMOVE_UUID 0x0011
struct mgmt_cp_remove_uuid {
__u8 uuid[16];
} __packed;
#define MGMT_REMOVE_UUID_SIZE 16
struct mgmt_link_key_info {
struct mgmt_addr_info addr;
__u8 type;
__u8 val[16];
__u8 pin_len;
} __packed;
#define MGMT_OP_LOAD_LINK_KEYS 0x0012
struct mgmt_cp_load_link_keys {
__u8 debug_keys;
__le16 key_count;
struct mgmt_link_key_info keys[0];
} __packed;
#define MGMT_LOAD_LINK_KEYS_SIZE 3
#define MGMT_LTK_UNAUTHENTICATED 0x00
#define MGMT_LTK_AUTHENTICATED 0x01
#define MGMT_LTK_P256_UNAUTH 0x02
#define MGMT_LTK_P256_AUTH 0x03
#define MGMT_LTK_P256_DEBUG 0x04
struct mgmt_ltk_info {
struct mgmt_addr_info addr;
__u8 type;
__u8 master;
__u8 enc_size;
__le16 ediv;
__le64 rand;
__u8 val[16];
} __packed;
#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013
struct mgmt_cp_load_long_term_keys {
__le16 key_count;
struct mgmt_ltk_info keys[0];
} __packed;
#define MGMT_LOAD_LONG_TERM_KEYS_SIZE 2
#define MGMT_OP_DISCONNECT 0x0014
struct mgmt_cp_disconnect {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_DISCONNECT_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_disconnect {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_GET_CONNECTIONS 0x0015
#define MGMT_GET_CONNECTIONS_SIZE 0
struct mgmt_rp_get_connections {
__le16 conn_count;
struct mgmt_addr_info addr[0];
} __packed;
#define MGMT_OP_PIN_CODE_REPLY 0x0016
struct mgmt_cp_pin_code_reply {
struct mgmt_addr_info addr;
__u8 pin_len;
__u8 pin_code[16];
} __packed;
#define MGMT_PIN_CODE_REPLY_SIZE (MGMT_ADDR_INFO_SIZE + 17)
struct mgmt_rp_pin_code_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017
struct mgmt_cp_pin_code_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_PIN_CODE_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_SET_IO_CAPABILITY 0x0018
struct mgmt_cp_set_io_capability {
__u8 io_capability;
} __packed;
#define MGMT_SET_IO_CAPABILITY_SIZE 1
#define MGMT_OP_PAIR_DEVICE 0x0019
struct mgmt_cp_pair_device {
struct mgmt_addr_info addr;
__u8 io_cap;
} __packed;
#define MGMT_PAIR_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
struct mgmt_rp_pair_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_CANCEL_PAIR_DEVICE 0x001A
#define MGMT_CANCEL_PAIR_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_UNPAIR_DEVICE 0x001B
struct mgmt_cp_unpair_device {
struct mgmt_addr_info addr;
__u8 disconnect;
} __packed;
#define MGMT_UNPAIR_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
struct mgmt_rp_unpair_device {
struct mgmt_addr_info addr;
};
#define MGMT_OP_USER_CONFIRM_REPLY 0x001C
struct mgmt_cp_user_confirm_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_USER_CONFIRM_REPLY_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_user_confirm_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001D
struct mgmt_cp_user_confirm_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_USER_CONFIRM_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_USER_PASSKEY_REPLY 0x001E
struct mgmt_cp_user_passkey_reply {
struct mgmt_addr_info addr;
__le32 passkey;
} __packed;
#define MGMT_USER_PASSKEY_REPLY_SIZE (MGMT_ADDR_INFO_SIZE + 4)
struct mgmt_rp_user_passkey_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001F
struct mgmt_cp_user_passkey_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_USER_PASSKEY_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0020
#define MGMT_READ_LOCAL_OOB_DATA_SIZE 0
struct mgmt_rp_read_local_oob_data {
__u8 hash192[16];
__u8 rand192[16];
__u8 hash256[16];
__u8 rand256[16];
} __packed;
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021
struct mgmt_cp_add_remote_oob_data {
struct mgmt_addr_info addr;
__u8 hash[16];
__u8 rand[16];
} __packed;
#define MGMT_ADD_REMOTE_OOB_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 32)
struct mgmt_cp_add_remote_oob_ext_data {
struct mgmt_addr_info addr;
__u8 hash192[16];
__u8 rand192[16];
__u8 hash256[16];
__u8 rand256[16];
} __packed;
#define MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 64)
#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0022
struct mgmt_cp_remove_remote_oob_data {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_REMOVE_REMOTE_OOB_DATA_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_START_DISCOVERY 0x0023
struct mgmt_cp_start_discovery {
__u8 type;
} __packed;
#define MGMT_START_DISCOVERY_SIZE 1
#define MGMT_OP_STOP_DISCOVERY 0x0024
struct mgmt_cp_stop_discovery {
__u8 type;
} __packed;
#define MGMT_STOP_DISCOVERY_SIZE 1
#define MGMT_OP_CONFIRM_NAME 0x0025
struct mgmt_cp_confirm_name {
struct mgmt_addr_info addr;
__u8 name_known;
} __packed;
#define MGMT_CONFIRM_NAME_SIZE (MGMT_ADDR_INFO_SIZE + 1)
struct mgmt_rp_confirm_name {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_BLOCK_DEVICE 0x0026
struct mgmt_cp_block_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_BLOCK_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_UNBLOCK_DEVICE 0x0027
struct mgmt_cp_unblock_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_UNBLOCK_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_SET_DEVICE_ID 0x0028
struct mgmt_cp_set_device_id {
__le16 source;
__le16 vendor;
__le16 product;
__le16 version;
} __packed;
#define MGMT_SET_DEVICE_ID_SIZE 8
#define MGMT_OP_SET_ADVERTISING 0x0029
#define MGMT_OP_SET_BREDR 0x002A
#define MGMT_OP_SET_STATIC_ADDRESS 0x002B
struct mgmt_cp_set_static_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_SET_STATIC_ADDRESS_SIZE 6
#define MGMT_OP_SET_SCAN_PARAMS 0x002C
struct mgmt_cp_set_scan_params {
__le16 interval;
__le16 window;
} __packed;
#define MGMT_SET_SCAN_PARAMS_SIZE 4
#define MGMT_OP_SET_SECURE_CONN 0x002D
#define MGMT_OP_SET_DEBUG_KEYS 0x002E
#define MGMT_OP_SET_PRIVACY 0x002F
struct mgmt_cp_set_privacy {
__u8 privacy;
__u8 irk[16];
} __packed;
#define MGMT_SET_PRIVACY_SIZE 17
struct mgmt_irk_info {
struct mgmt_addr_info addr;
__u8 val[16];
} __packed;
#define MGMT_OP_LOAD_IRKS 0x0030
struct mgmt_cp_load_irks {
__le16 irk_count;
struct mgmt_irk_info irks[0];
} __packed;
#define MGMT_LOAD_IRKS_SIZE 2
#define MGMT_OP_GET_CONN_INFO 0x0031
struct mgmt_cp_get_conn_info {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_GET_CONN_INFO_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_get_conn_info {
struct mgmt_addr_info addr;
__s8 rssi;
__s8 tx_power;
__s8 max_tx_power;
} __packed;
#define MGMT_OP_GET_CLOCK_INFO 0x0032
struct mgmt_cp_get_clock_info {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_GET_CLOCK_INFO_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_get_clock_info {
struct mgmt_addr_info addr;
__le32 local_clock;
__le32 piconet_clock;
__le16 accuracy;
} __packed;
#define MGMT_OP_ADD_DEVICE 0x0033
struct mgmt_cp_add_device {
struct mgmt_addr_info addr;
__u8 action;
} __packed;
#define MGMT_ADD_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
#define MGMT_OP_REMOVE_DEVICE 0x0034
struct mgmt_cp_remove_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_REMOVE_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_conn_param {
struct mgmt_addr_info addr;
__le16 min_interval;
__le16 max_interval;
__le16 latency;
__le16 timeout;
} __packed;
#define MGMT_OP_LOAD_CONN_PARAM 0x0035
struct mgmt_cp_load_conn_param {
__le16 param_count;
struct mgmt_conn_param params[0];
} __packed;
#define MGMT_LOAD_CONN_PARAM_SIZE 2
#define MGMT_OP_READ_UNCONF_INDEX_LIST 0x0036
#define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0
struct mgmt_rp_read_unconf_index_list {
__le16 num_controllers;
__le16 index[0];
} __packed;
#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001
#define MGMT_OPTION_PUBLIC_ADDRESS 0x00000002
#define MGMT_OP_READ_CONFIG_INFO 0x0037
#define MGMT_READ_CONFIG_INFO_SIZE 0
struct mgmt_rp_read_config_info {
__le16 manufacturer;
__le32 supported_options;
__le32 missing_options;
} __packed;
#define MGMT_OP_SET_EXTERNAL_CONFIG 0x0038
struct mgmt_cp_set_external_config {
__u8 config;
} __packed;
#define MGMT_SET_EXTERNAL_CONFIG_SIZE 1
#define MGMT_OP_SET_PUBLIC_ADDRESS 0x0039
struct mgmt_cp_set_public_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_SET_PUBLIC_ADDRESS_SIZE 6
#define MGMT_OP_START_SERVICE_DISCOVERY 0x003A
struct mgmt_cp_start_service_discovery {
__u8 type;
__s8 rssi;
__le16 uuid_count;
__u8 uuids[0][16];
} __packed;
#define MGMT_START_SERVICE_DISCOVERY_SIZE 4
#define MGMT_OP_READ_LOCAL_OOB_EXT_DATA 0x003B
struct mgmt_cp_read_local_oob_ext_data {
__u8 type;
} __packed;
#define MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE 1
struct mgmt_rp_read_local_oob_ext_data {
__u8 type;
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C
#define MGMT_READ_EXT_INDEX_LIST_SIZE 0
struct mgmt_rp_read_ext_index_list {
__le16 num_controllers;
struct {
__le16 index;
__u8 type;
__u8 bus;
} entry[0];
} __packed;
#define MGMT_OP_READ_ADV_FEATURES 0x0003D
#define MGMT_READ_ADV_FEATURES_SIZE 0
struct mgmt_rp_read_adv_features {
__le32 supported_flags;
__u8 max_adv_data_len;
__u8 max_scan_rsp_len;
__u8 max_instances;
__u8 num_instances;
__u8 instance[0];
} __packed;
#define MGMT_OP_ADD_ADVERTISING 0x003E
struct mgmt_cp_add_advertising {
__u8 instance;
__le32 flags;
__le16 duration;
__le16 timeout;
__u8 adv_data_len;
__u8 scan_rsp_len;
__u8 data[0];
} __packed;
#define MGMT_ADD_ADVERTISING_SIZE 11
struct mgmt_rp_add_advertising {
__u8 instance;
} __packed;
#define MGMT_ADV_FLAG_CONNECTABLE BIT(0)
#define MGMT_ADV_FLAG_DISCOV BIT(1)
#define MGMT_ADV_FLAG_LIMITED_DISCOV BIT(2)
#define MGMT_ADV_FLAG_MANAGED_FLAGS BIT(3)
#define MGMT_ADV_FLAG_TX_POWER BIT(4)
#define MGMT_ADV_FLAG_APPEARANCE BIT(5)
#define MGMT_ADV_FLAG_LOCAL_NAME BIT(6)
#define MGMT_ADV_FLAG_SEC_1M BIT(7)
#define MGMT_ADV_FLAG_SEC_2M BIT(8)
#define MGMT_ADV_FLAG_SEC_CODED BIT(9)
#define MGMT_ADV_FLAG_SEC_MASK (MGMT_ADV_FLAG_SEC_1M | MGMT_ADV_FLAG_SEC_2M | \
MGMT_ADV_FLAG_SEC_CODED)
#define MGMT_OP_REMOVE_ADVERTISING 0x003F
struct mgmt_cp_remove_advertising {
__u8 instance;
} __packed;
#define MGMT_REMOVE_ADVERTISING_SIZE 1
struct mgmt_rp_remove_advertising {
__u8 instance;
} __packed;
#define MGMT_OP_GET_ADV_SIZE_INFO 0x0040
struct mgmt_cp_get_adv_size_info {
__u8 instance;
__le32 flags;
} __packed;
#define MGMT_GET_ADV_SIZE_INFO_SIZE 5
struct mgmt_rp_get_adv_size_info {
__u8 instance;
__le32 flags;
__u8 max_adv_data_len;
__u8 max_scan_rsp_len;
} __packed;
#define MGMT_OP_START_LIMITED_DISCOVERY 0x0041
#define MGMT_OP_READ_EXT_INFO 0x0042
#define MGMT_READ_EXT_INFO_SIZE 0
struct mgmt_rp_read_ext_info {
bdaddr_t bdaddr;
__u8 version;
__le16 manufacturer;
__le32 supported_settings;
__le32 current_settings;
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_OP_SET_APPEARANCE 0x0043
struct mgmt_cp_set_appearance {
__le16 appearance;
} __packed;
#define MGMT_SET_APPEARANCE_SIZE 2
#define MGMT_OP_GET_PHY_CONFIGURATION 0x0044
struct mgmt_rp_get_phy_confguration {
__le32 supported_phys;
__le32 configurable_phys;
__le32 selected_phys;
} __packed;
#define MGMT_GET_PHY_CONFIGURATION_SIZE 0
#define MGMT_PHY_BR_1M_1SLOT 0x00000001
#define MGMT_PHY_BR_1M_3SLOT 0x00000002
#define MGMT_PHY_BR_1M_5SLOT 0x00000004
#define MGMT_PHY_EDR_2M_1SLOT 0x00000008
#define MGMT_PHY_EDR_2M_3SLOT 0x00000010
#define MGMT_PHY_EDR_2M_5SLOT 0x00000020
#define MGMT_PHY_EDR_3M_1SLOT 0x00000040
#define MGMT_PHY_EDR_3M_3SLOT 0x00000080
#define MGMT_PHY_EDR_3M_5SLOT 0x00000100
#define MGMT_PHY_LE_1M_TX 0x00000200
#define MGMT_PHY_LE_1M_RX 0x00000400
#define MGMT_PHY_LE_2M_TX 0x00000800
#define MGMT_PHY_LE_2M_RX 0x00001000
#define MGMT_PHY_LE_CODED_TX 0x00002000
#define MGMT_PHY_LE_CODED_RX 0x00004000
#define MGMT_PHY_BREDR_MASK (MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_BR_1M_3SLOT | \
MGMT_PHY_BR_1M_5SLOT | MGMT_PHY_EDR_2M_1SLOT | \
MGMT_PHY_EDR_2M_3SLOT | MGMT_PHY_EDR_2M_5SLOT | \
MGMT_PHY_EDR_3M_1SLOT | MGMT_PHY_EDR_3M_3SLOT | \
MGMT_PHY_EDR_3M_5SLOT)
#define MGMT_PHY_LE_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX | \
MGMT_PHY_LE_2M_TX | MGMT_PHY_LE_2M_RX | \
MGMT_PHY_LE_CODED_TX | MGMT_PHY_LE_CODED_RX)
#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
MGMT_PHY_LE_CODED_TX)
#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \
MGMT_PHY_LE_CODED_RX)
#define MGMT_OP_SET_PHY_CONFIGURATION 0x0045
struct mgmt_cp_set_phy_confguration {
__le32 selected_phys;
} __packed;
#define MGMT_SET_PHY_CONFIGURATION_SIZE 4
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
__u8 status;
__u8 data[0];
} __packed;
#define MGMT_EV_CMD_STATUS 0x0002
struct mgmt_ev_cmd_status {
__le16 opcode;
__u8 status;
} __packed;
#define MGMT_EV_CONTROLLER_ERROR 0x0003
struct mgmt_ev_controller_error {
__u8 error_code;
} __packed;
#define MGMT_EV_INDEX_ADDED 0x0004
#define MGMT_EV_INDEX_REMOVED 0x0005
#define MGMT_EV_NEW_SETTINGS 0x0006
#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007
struct mgmt_ev_class_of_dev_changed {
__u8 dev_class[3];
};
#define MGMT_EV_LOCAL_NAME_CHANGED 0x0008
struct mgmt_ev_local_name_changed {
__u8 name[MGMT_MAX_NAME_LENGTH];
__u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
#define MGMT_EV_NEW_LINK_KEY 0x0009
struct mgmt_ev_new_link_key {
__u8 store_hint;
struct mgmt_link_key_info key;
} __packed;
#define MGMT_EV_NEW_LONG_TERM_KEY 0x000A
struct mgmt_ev_new_long_term_key {
__u8 store_hint;
struct mgmt_ltk_info key;
} __packed;
#define MGMT_EV_DEVICE_CONNECTED 0x000B
struct mgmt_ev_device_connected {
struct mgmt_addr_info addr;
__le32 flags;
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_DEV_DISCONN_UNKNOWN 0x00
#define MGMT_DEV_DISCONN_TIMEOUT 0x01
#define MGMT_DEV_DISCONN_LOCAL_HOST 0x02
#define MGMT_DEV_DISCONN_REMOTE 0x03
#define MGMT_DEV_DISCONN_AUTH_FAILURE 0x04
#define MGMT_EV_DEVICE_DISCONNECTED 0x000C
struct mgmt_ev_device_disconnected {
struct mgmt_addr_info addr;
__u8 reason;
} __packed;
#define MGMT_EV_CONNECT_FAILED 0x000D
struct mgmt_ev_connect_failed {
struct mgmt_addr_info addr;
__u8 status;
} __packed;
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct mgmt_ev_pin_code_request {
struct mgmt_addr_info addr;
__u8 secure;
} __packed;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
struct mgmt_ev_user_confirm_request {
struct mgmt_addr_info addr;
__u8 confirm_hint;
__le32 value;
} __packed;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x0010
struct mgmt_ev_user_passkey_request {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_AUTH_FAILED 0x0011
struct mgmt_ev_auth_failed {
struct mgmt_addr_info addr;
__u8 status;
} __packed;
#define MGMT_DEV_FOUND_CONFIRM_NAME 0x01
#define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02
#define MGMT_DEV_FOUND_NOT_CONNECTABLE 0x04
#define MGMT_EV_DEVICE_FOUND 0x0012
struct mgmt_ev_device_found {
struct mgmt_addr_info addr;
__s8 rssi;
__le32 flags;
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_EV_DISCOVERING 0x0013
struct mgmt_ev_discovering {
__u8 type;
__u8 discovering;
} __packed;
#define MGMT_EV_DEVICE_BLOCKED 0x0014
struct mgmt_ev_device_blocked {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_DEVICE_UNBLOCKED 0x0015
struct mgmt_ev_device_unblocked {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_DEVICE_UNPAIRED 0x0016
struct mgmt_ev_device_unpaired {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_PASSKEY_NOTIFY 0x0017
struct mgmt_ev_passkey_notify {
struct mgmt_addr_info addr;
__le32 passkey;
__u8 entered;
} __packed;
#define MGMT_EV_NEW_IRK 0x0018
struct mgmt_ev_new_irk {
__u8 store_hint;
bdaddr_t rpa;
struct mgmt_irk_info irk;
} __packed;
#define MGMT_CSRK_LOCAL_UNAUTHENTICATED 0x00
#define MGMT_CSRK_REMOTE_UNAUTHENTICATED 0x01
#define MGMT_CSRK_LOCAL_AUTHENTICATED 0x02
#define MGMT_CSRK_REMOTE_AUTHENTICATED 0x03
struct mgmt_csrk_info {
struct mgmt_addr_info addr;
__u8 type;
__u8 val[16];
} __packed;
#define MGMT_EV_NEW_CSRK 0x0019
struct mgmt_ev_new_csrk {
__u8 store_hint;
struct mgmt_csrk_info key;
} __packed;
#define MGMT_EV_DEVICE_ADDED 0x001a
struct mgmt_ev_device_added {
struct mgmt_addr_info addr;
__u8 action;
} __packed;
#define MGMT_EV_DEVICE_REMOVED 0x001b
struct mgmt_ev_device_removed {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_NEW_CONN_PARAM 0x001c
struct mgmt_ev_new_conn_param {
struct mgmt_addr_info addr;
__u8 store_hint;
__le16 min_interval;
__le16 max_interval;
__le16 latency;
__le16 timeout;
} __packed;
#define MGMT_EV_UNCONF_INDEX_ADDED 0x001d
#define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e
#define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f
struct mgmt_ev_ext_index {
__u8 type;
__u8 bus;
} __packed;
#define MGMT_EV_EXT_INDEX_ADDED 0x0020
#define MGMT_EV_EXT_INDEX_REMOVED 0x0021
#define MGMT_EV_LOCAL_OOB_DATA_UPDATED 0x0022
struct mgmt_ev_local_oob_data_updated {
__u8 type;
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_EV_ADVERTISING_ADDED 0x0023
struct mgmt_ev_advertising_added {
__u8 instance;
} __packed;
#define MGMT_EV_ADVERTISING_REMOVED 0x0024
struct mgmt_ev_advertising_removed {
__u8 instance;
} __packed;
#define MGMT_EV_EXT_INFO_CHANGED 0x0025
struct mgmt_ev_ext_info_changed {
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_EV_PHY_CONFIGURATION_CHANGED 0x0026
struct mgmt_ev_phy_configuration_changed {
__le32 selected_phys;
} __packed;
+376
View File
@@ -0,0 +1,376 @@
/*
RFCOMM implementation for Linux Bluetooth stack (BlueZ)
Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#include <linux/refcount.h>
#ifndef __RFCOMM_H
#define __RFCOMM_H
#define RFCOMM_CONN_TIMEOUT (HZ * 30)
#define RFCOMM_DISC_TIMEOUT (HZ * 20)
#define RFCOMM_AUTH_TIMEOUT (HZ * 25)
#define RFCOMM_IDLE_TIMEOUT (HZ * 2)
#define RFCOMM_DEFAULT_MTU 127
#define RFCOMM_DEFAULT_CREDITS 7
#define RFCOMM_MAX_L2CAP_MTU 1013
#define RFCOMM_MAX_CREDITS 40
#define RFCOMM_SKB_HEAD_RESERVE 8
#define RFCOMM_SKB_TAIL_RESERVE 2
#define RFCOMM_SKB_RESERVE (RFCOMM_SKB_HEAD_RESERVE + RFCOMM_SKB_TAIL_RESERVE)
#define RFCOMM_SABM 0x2f
#define RFCOMM_DISC 0x43
#define RFCOMM_UA 0x63
#define RFCOMM_DM 0x0f
#define RFCOMM_UIH 0xef
#define RFCOMM_TEST 0x08
#define RFCOMM_FCON 0x28
#define RFCOMM_FCOFF 0x18
#define RFCOMM_MSC 0x38
#define RFCOMM_RPN 0x24
#define RFCOMM_RLS 0x14
#define RFCOMM_PN 0x20
#define RFCOMM_NSC 0x04
#define RFCOMM_V24_FC 0x02
#define RFCOMM_V24_RTC 0x04
#define RFCOMM_V24_RTR 0x08
#define RFCOMM_V24_IC 0x40
#define RFCOMM_V24_DV 0x80
#define RFCOMM_RPN_BR_2400 0x0
#define RFCOMM_RPN_BR_4800 0x1
#define RFCOMM_RPN_BR_7200 0x2
#define RFCOMM_RPN_BR_9600 0x3
#define RFCOMM_RPN_BR_19200 0x4
#define RFCOMM_RPN_BR_38400 0x5
#define RFCOMM_RPN_BR_57600 0x6
#define RFCOMM_RPN_BR_115200 0x7
#define RFCOMM_RPN_BR_230400 0x8
#define RFCOMM_RPN_DATA_5 0x0
#define RFCOMM_RPN_DATA_6 0x1
#define RFCOMM_RPN_DATA_7 0x2
#define RFCOMM_RPN_DATA_8 0x3
#define RFCOMM_RPN_STOP_1 0
#define RFCOMM_RPN_STOP_15 1
#define RFCOMM_RPN_PARITY_NONE 0x0
#define RFCOMM_RPN_PARITY_ODD 0x1
#define RFCOMM_RPN_PARITY_EVEN 0x3
#define RFCOMM_RPN_PARITY_MARK 0x5
#define RFCOMM_RPN_PARITY_SPACE 0x7
#define RFCOMM_RPN_FLOW_NONE 0x00
#define RFCOMM_RPN_XON_CHAR 0x11
#define RFCOMM_RPN_XOFF_CHAR 0x13
#define RFCOMM_RPN_PM_BITRATE 0x0001
#define RFCOMM_RPN_PM_DATA 0x0002
#define RFCOMM_RPN_PM_STOP 0x0004
#define RFCOMM_RPN_PM_PARITY 0x0008
#define RFCOMM_RPN_PM_PARITY_TYPE 0x0010
#define RFCOMM_RPN_PM_XON 0x0020
#define RFCOMM_RPN_PM_XOFF 0x0040
#define RFCOMM_RPN_PM_FLOW 0x3F00
#define RFCOMM_RPN_PM_ALL 0x3F7F
struct rfcomm_hdr {
u8 addr;
u8 ctrl;
u8 len; /* Actual size can be 2 bytes */
} __packed;
struct rfcomm_cmd {
u8 addr;
u8 ctrl;
u8 len;
u8 fcs;
} __packed;
struct rfcomm_mcc {
u8 type;
u8 len;
} __packed;
struct rfcomm_pn {
u8 dlci;
u8 flow_ctrl;
u8 priority;
u8 ack_timer;
__le16 mtu;
u8 max_retrans;
u8 credits;
} __packed;
struct rfcomm_rpn {
u8 dlci;
u8 bit_rate;
u8 line_settings;
u8 flow_ctrl;
u8 xon_char;
u8 xoff_char;
__le16 param_mask;
} __packed;
struct rfcomm_rls {
u8 dlci;
u8 status;
} __packed;
struct rfcomm_msc {
u8 dlci;
u8 v24_sig;
} __packed;
/* ---- Core structures, flags etc ---- */
struct rfcomm_session {
struct list_head list;
struct socket *sock;
struct timer_list timer;
unsigned long state;
unsigned long flags;
int initiator;
/* Default DLC parameters */
int cfc;
uint mtu;
struct list_head dlcs;
};
struct rfcomm_dlc {
struct list_head list;
struct rfcomm_session *session;
struct sk_buff_head tx_queue;
struct timer_list timer;
struct mutex lock;
unsigned long state;
unsigned long flags;
refcount_t refcnt;
u8 dlci;
u8 addr;
u8 priority;
u8 v24_sig;
u8 remote_v24_sig;
u8 mscex;
u8 out;
u8 sec_level;
u8 role_switch;
u32 defer_setup;
uint mtu;
uint cfc;
uint rx_credits;
uint tx_credits;
void *owner;
void (*data_ready)(struct rfcomm_dlc *d, struct sk_buff *skb);
void (*state_change)(struct rfcomm_dlc *d, int err);
void (*modem_status)(struct rfcomm_dlc *d, u8 v24_sig);
};
/* DLC and session flags */
#define RFCOMM_RX_THROTTLED 0
#define RFCOMM_TX_THROTTLED 1
#define RFCOMM_TIMED_OUT 2
#define RFCOMM_MSC_PENDING 3
#define RFCOMM_SEC_PENDING 4
#define RFCOMM_AUTH_PENDING 5
#define RFCOMM_AUTH_ACCEPT 6
#define RFCOMM_AUTH_REJECT 7
#define RFCOMM_DEFER_SETUP 8
#define RFCOMM_ENC_DROP 9
/* Scheduling flags and events */
#define RFCOMM_SCHED_WAKEUP 31
/* MSC exchange flags */
#define RFCOMM_MSCEX_TX 1
#define RFCOMM_MSCEX_RX 2
#define RFCOMM_MSCEX_OK (RFCOMM_MSCEX_TX + RFCOMM_MSCEX_RX)
/* CFC states */
#define RFCOMM_CFC_UNKNOWN -1
#define RFCOMM_CFC_DISABLED 0
#define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS
/* ---- RFCOMM SEND RPN ---- */
int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
u8 bit_rate, u8 data_bits, u8 stop_bits,
u8 parity, u8 flow_ctrl_settings,
u8 xon_char, u8 xoff_char, u16 param_mask);
/* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d);
int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
u8 channel);
int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb);
int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
void rfcomm_dlc_accept(struct rfcomm_dlc *d);
struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
#define rfcomm_dlc_lock(d) mutex_lock(&d->lock)
#define rfcomm_dlc_unlock(d) mutex_unlock(&d->lock)
static inline void rfcomm_dlc_hold(struct rfcomm_dlc *d)
{
refcount_inc(&d->refcnt);
}
static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
{
if (refcount_dec_and_test(&d->refcnt))
rfcomm_dlc_free(d);
}
void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
static inline void rfcomm_dlc_throttle(struct rfcomm_dlc *d)
{
if (!test_and_set_bit(RFCOMM_RX_THROTTLED, &d->flags))
__rfcomm_dlc_throttle(d);
}
static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
{
if (test_and_clear_bit(RFCOMM_RX_THROTTLED, &d->flags))
__rfcomm_dlc_unthrottle(d);
}
/* ---- RFCOMM sessions ---- */
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
bdaddr_t *dst);
/* ---- RFCOMM sockets ---- */
struct sockaddr_rc {
sa_family_t rc_family;
bdaddr_t rc_bdaddr;
u8 rc_channel;
};
#define RFCOMM_CONNINFO 0x02
struct rfcomm_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define RFCOMM_LM 0x03
#define RFCOMM_LM_MASTER 0x0001
#define RFCOMM_LM_AUTH 0x0002
#define RFCOMM_LM_ENCRYPT 0x0004
#define RFCOMM_LM_TRUSTED 0x0008
#define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020
#define RFCOMM_LM_FIPS 0x0040
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
struct rfcomm_pinfo {
struct bt_sock bt;
bdaddr_t src;
bdaddr_t dst;
struct rfcomm_dlc *dlc;
u8 channel;
u8 sec_level;
u8 role_switch;
};
int rfcomm_init_sockets(void);
void rfcomm_cleanup_sockets(void);
int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
struct rfcomm_dlc **d);
/* ---- RFCOMM TTY ---- */
#define RFCOMM_MAX_DEV 256
#define RFCOMMCREATEDEV _IOW('R', 200, int)
#define RFCOMMRELEASEDEV _IOW('R', 201, int)
#define RFCOMMGETDEVLIST _IOR('R', 210, int)
#define RFCOMMGETDEVINFO _IOR('R', 211, int)
#define RFCOMMSTEALDLC _IOW('R', 220, int)
/* rfcomm_dev.flags bit definitions */
#define RFCOMM_REUSE_DLC 0
#define RFCOMM_RELEASE_ONHUP 1
#define RFCOMM_HANGUP_NOW 2
#define RFCOMM_TTY_ATTACHED 3
#define RFCOMM_DEFUNCT_BIT4 4 /* don't reuse this bit - userspace visible */
/* rfcomm_dev.status bit definitions */
#define RFCOMM_DEV_RELEASED 0
#define RFCOMM_TTY_OWNED 1
struct rfcomm_dev_req {
s16 dev_id;
u32 flags;
bdaddr_t src;
bdaddr_t dst;
u8 channel;
};
struct rfcomm_dev_info {
s16 id;
u32 flags;
u16 state;
bdaddr_t src;
bdaddr_t dst;
u8 channel;
};
struct rfcomm_dev_list_req {
u16 dev_num;
struct rfcomm_dev_info dev_info[0];
};
int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
#ifdef CONFIG_BT_RFCOMM_TTY
int rfcomm_init_ttys(void);
void rfcomm_cleanup_ttys(void);
#else
static inline int rfcomm_init_ttys(void)
{
return 0;
}
static inline void rfcomm_cleanup_ttys(void)
{
}
#endif
#endif /* __RFCOMM_H */
+49
View File
@@ -0,0 +1,49 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __SCO_H
#define __SCO_H
/* SCO defaults */
#define SCO_DEFAULT_MTU 500
/* SCO socket address */
struct sockaddr_sco {
sa_family_t sco_family;
bdaddr_t sco_bdaddr;
};
/* SCO socket options */
#define SCO_OPTIONS 0x01
struct sco_options {
__u16 mtu;
};
#define SCO_CONNINFO 0x02
struct sco_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#endif /* __SCO_H */
+311
View File
@@ -0,0 +1,311 @@
/*
* Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#ifndef _NET_BOND_3AD_H
#define _NET_BOND_3AD_H
#include <asm/byteorder.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
/* General definitions */
#define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW)
#define AD_TIMER_INTERVAL 100 /*msec*/
#define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
#define AD_LACP_SLOW 0
#define AD_LACP_FAST 1
typedef struct mac_addr {
u8 mac_addr_value[ETH_ALEN];
} __packed mac_addr_t;
enum {
BOND_AD_STABLE = 0,
BOND_AD_BANDWIDTH = 1,
BOND_AD_COUNT = 2,
};
/* rx machine states(43.4.11 in the 802.3ad standard) */
typedef enum {
AD_RX_DUMMY,
AD_RX_INITIALIZE, /* rx Machine */
AD_RX_PORT_DISABLED, /* rx Machine */
AD_RX_LACP_DISABLED, /* rx Machine */
AD_RX_EXPIRED, /* rx Machine */
AD_RX_DEFAULTED, /* rx Machine */
AD_RX_CURRENT /* rx Machine */
} rx_states_t;
/* periodic machine states(43.4.12 in the 802.3ad standard) */
typedef enum {
AD_PERIODIC_DUMMY,
AD_NO_PERIODIC, /* periodic machine */
AD_FAST_PERIODIC, /* periodic machine */
AD_SLOW_PERIODIC, /* periodic machine */
AD_PERIODIC_TX /* periodic machine */
} periodic_states_t;
/* mux machine states(43.4.13 in the 802.3ad standard) */
typedef enum {
AD_MUX_DUMMY,
AD_MUX_DETACHED, /* mux machine */
AD_MUX_WAITING, /* mux machine */
AD_MUX_ATTACHED, /* mux machine */
AD_MUX_COLLECTING_DISTRIBUTING /* mux machine */
} mux_states_t;
/* tx machine states(43.4.15 in the 802.3ad standard) */
typedef enum {
AD_TX_DUMMY,
AD_TRANSMIT /* tx Machine */
} tx_states_t;
/* churn machine states(43.4.17 in the 802.3ad standard) */
typedef enum {
AD_CHURN_MONITOR, /* monitoring for churn */
AD_CHURN, /* churn detected (error) */
AD_NO_CHURN /* no churn (no error) */
} churn_state_t;
/* rx indication types */
typedef enum {
AD_TYPE_LACPDU = 1, /* type lacpdu */
AD_TYPE_MARKER /* type marker */
} pdu_type_t;
/* rx marker indication types */
typedef enum {
AD_MARKER_INFORMATION_SUBTYPE = 1, /* marker imformation subtype */
AD_MARKER_RESPONSE_SUBTYPE /* marker response subtype */
} bond_marker_subtype_t;
/* timers types(43.4.9 in the 802.3ad standard) */
typedef enum {
AD_CURRENT_WHILE_TIMER,
AD_ACTOR_CHURN_TIMER,
AD_PERIODIC_TIMER,
AD_PARTNER_CHURN_TIMER,
AD_WAIT_WHILE_TIMER
} ad_timers_t;
#pragma pack(1)
/* Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard) */
typedef struct lacpdu {
u8 subtype; /* = LACP(= 0x01) */
u8 version_number;
u8 tlv_type_actor_info; /* = actor information(type/length/value) */
u8 actor_information_length; /* = 20 */
__be16 actor_system_priority;
struct mac_addr actor_system;
__be16 actor_key;
__be16 actor_port_priority;
__be16 actor_port;
u8 actor_state;
u8 reserved_3_1[3]; /* = 0 */
u8 tlv_type_partner_info; /* = partner information */
u8 partner_information_length; /* = 20 */
__be16 partner_system_priority;
struct mac_addr partner_system;
__be16 partner_key;
__be16 partner_port_priority;
__be16 partner_port;
u8 partner_state;
u8 reserved_3_2[3]; /* = 0 */
u8 tlv_type_collector_info; /* = collector information */
u8 collector_information_length;/* = 16 */
__be16 collector_max_delay;
u8 reserved_12[12];
u8 tlv_type_terminator; /* = terminator */
u8 terminator_length; /* = 0 */
u8 reserved_50[50]; /* = 0 */
} __packed lacpdu_t;
typedef struct lacpdu_header {
struct ethhdr hdr;
struct lacpdu lacpdu;
} __packed lacpdu_header_t;
/* Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) */
typedef struct bond_marker {
u8 subtype; /* = 0x02 (marker PDU) */
u8 version_number; /* = 0x01 */
u8 tlv_type; /* = 0x01 (marker information) */
/* = 0x02 (marker response information) */
u8 marker_length; /* = 0x16 */
u16 requester_port; /* The number assigned to the port by the requester */
struct mac_addr requester_system; /* The requester's system id */
u32 requester_transaction_id; /* The transaction id allocated by the requester, */
u16 pad; /* = 0 */
u8 tlv_type_terminator; /* = 0x00 */
u8 terminator_length; /* = 0x00 */
u8 reserved_90[90]; /* = 0 */
} __packed bond_marker_t;
typedef struct bond_marker_header {
struct ethhdr hdr;
struct bond_marker marker;
} __packed bond_marker_header_t;
#pragma pack()
struct slave;
struct bonding;
struct ad_info;
struct port;
#ifdef __ia64__
#pragma pack(8)
#endif
/* aggregator structure(43.4.5 in the 802.3ad standard) */
typedef struct aggregator {
struct mac_addr aggregator_mac_address;
u16 aggregator_identifier;
bool is_individual;
u16 actor_admin_aggregator_key;
u16 actor_oper_aggregator_key;
struct mac_addr partner_system;
u16 partner_system_priority;
u16 partner_oper_aggregator_key;
u16 receive_state; /* BOOLEAN */
u16 transmit_state; /* BOOLEAN */
struct port *lag_ports;
/* ****** PRIVATE PARAMETERS ****** */
struct slave *slave; /* pointer to the bond slave that this aggregator belongs to */
u16 is_active; /* BOOLEAN. Indicates if this aggregator is active */
u16 num_of_ports;
} aggregator_t;
struct port_params {
struct mac_addr system;
u16 system_priority;
u16 key;
u16 port_number;
u16 port_priority;
u16 port_state;
};
/* port structure(43.4.6 in the 802.3ad standard) */
typedef struct port {
u16 actor_port_number;
u16 actor_port_priority;
struct mac_addr actor_system; /* This parameter is added here although it is not specified in the standard, just for simplification */
u16 actor_system_priority; /* This parameter is added here although it is not specified in the standard, just for simplification */
u16 actor_port_aggregator_identifier;
bool ntt;
u16 actor_admin_port_key;
u16 actor_oper_port_key;
u8 actor_admin_port_state;
u8 actor_oper_port_state;
struct port_params partner_admin;
struct port_params partner_oper;
bool is_enabled;
/* ****** PRIVATE PARAMETERS ****** */
u16 sm_vars; /* all state machines variables for this port */
rx_states_t sm_rx_state; /* state machine rx state */
u16 sm_rx_timer_counter; /* state machine rx timer counter */
periodic_states_t sm_periodic_state; /* state machine periodic state */
u16 sm_periodic_timer_counter; /* state machine periodic timer counter */
mux_states_t sm_mux_state; /* state machine mux state */
u16 sm_mux_timer_counter; /* state machine mux timer counter */
tx_states_t sm_tx_state; /* state machine tx state */
u16 sm_tx_timer_counter; /* state machine tx timer counter(allways on - enter to transmit state 3 time per second) */
u16 sm_churn_actor_timer_counter;
u16 sm_churn_partner_timer_counter;
u32 churn_actor_count;
u32 churn_partner_count;
churn_state_t sm_churn_actor_state;
churn_state_t sm_churn_partner_state;
struct slave *slave; /* pointer to the bond slave that this port belongs to */
struct aggregator *aggregator; /* pointer to an aggregator that this port related to */
struct port *next_port_in_aggregator; /* Next port on the linked list of the parent aggregator */
u32 transaction_id; /* continuous number for identification of Marker PDU's; */
struct lacpdu lacpdu; /* the lacpdu that will be sent for this port */
} port_t;
/* system structure */
struct ad_system {
u16 sys_priority;
struct mac_addr sys_mac_addr;
};
#ifdef __ia64__
#pragma pack()
#endif
/* ========== AD Exported structures to the main bonding code ========== */
#define BOND_AD_INFO(bond) ((bond)->ad_info)
#define SLAVE_AD_INFO(slave) ((slave)->ad_info)
struct ad_bond_info {
struct ad_system system; /* 802.3ad system structure */
u32 agg_select_timer; /* Timer to select aggregator after all adapter's hand shakes */
u16 aggregator_identifier;
};
struct ad_slave_info {
struct aggregator aggregator; /* 802.3ad aggregator structure */
struct port port; /* 802.3ad port structure */
u16 id;
};
static inline const char *bond_3ad_churn_desc(churn_state_t state)
{
static const char *const churn_description[] = {
"monitoring",
"churned",
"none",
"unknown"
};
int max_size = ARRAY_SIZE(churn_description);
if (state >= max_size)
state = max_size - 1;
return churn_description[state];
}
/* ========== AD Exported functions to the main bonding code ========== */
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
void bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
void bond_3ad_adapter_speed_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int __bond_3ad_get_active_agg_info(struct bonding *bond,
struct ad_info *ad_info);
int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond);
void bond_3ad_update_lacp_rate(struct bonding *bond);
void bond_3ad_update_ad_actor_settings(struct bonding *bond);
#endif /* _NET_BOND_3AD_H */
+181
View File
@@ -0,0 +1,181 @@
/*
* Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#ifndef _NET_BOND_ALB_H
#define _NET_BOND_ALB_H
#include <linux/if_ether.h>
struct bonding;
struct slave;
#define BOND_ALB_INFO(bond) ((bond)->alb_info)
#define SLAVE_TLB_INFO(slave) ((slave)->tlb_info)
#define ALB_TIMER_TICKS_PER_SEC 10 /* should be a divisor of HZ */
#define BOND_TLB_REBALANCE_INTERVAL 10 /* In seconds, periodic re-balancing.
* Used for division - never set
* to zero !!!
*/
#define BOND_ALB_DEFAULT_LP_INTERVAL 1
#define BOND_ALB_LP_INTERVAL(bond) (bond->params.lp_interval) /* In seconds, periodic send of
* learning packets to the switch
*/
#define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \
* ALB_TIMER_TICKS_PER_SEC)
#define BOND_ALB_LP_TICKS(bond) (BOND_ALB_LP_INTERVAL(bond) \
* ALB_TIMER_TICKS_PER_SEC)
#define TLB_HASH_TABLE_SIZE 256 /* The size of the clients hash table.
* Note that this value MUST NOT be smaller
* because the key hash table is BYTE wide !
*/
#define TLB_NULL_INDEX 0xffffffff
/* rlb defs */
#define RLB_HASH_TABLE_SIZE 256
#define RLB_NULL_INDEX 0xffffffff
#define RLB_UPDATE_DELAY (2*ALB_TIMER_TICKS_PER_SEC) /* 2 seconds */
#define RLB_ARP_BURST_SIZE 2
#define RLB_UPDATE_RETRY 3 /* 3-ticks - must be smaller than the rlb
* rebalance interval (5 min).
*/
/* RLB_PROMISC_TIMEOUT = 10 sec equals the time that the current slave is
* promiscuous after failover
*/
#define RLB_PROMISC_TIMEOUT (10*ALB_TIMER_TICKS_PER_SEC)
struct tlb_client_info {
struct slave *tx_slave; /* A pointer to slave used for transmiting
* packets to a Client that the Hash function
* gave this entry index.
*/
u32 tx_bytes; /* Each Client accumulates the BytesTx that
* were transmitted to it, and after each
* CallBack the LoadHistory is divided
* by the balance interval
*/
u32 load_history; /* This field contains the amount of Bytes
* that were transmitted to this client by
* the server on the previous balance
* interval in Bps.
*/
u32 next; /* The next Hash table entry index, assigned
* to use the same adapter for transmit.
*/
u32 prev; /* The previous Hash table entry index,
* assigned to use the same
*/
};
/* -------------------------------------------------------------------------
* struct rlb_client_info contains all info related to a specific rx client
* connection. This is the Clients Hash Table entry struct.
* Note that this is not a proper hash table; if a new client's IP address
* hash collides with an existing client entry, the old entry is replaced.
*
* There is a linked list (linked by the used_next and used_prev members)
* linking all the used entries of the hash table. This allows updating
* all the clients without walking over all the unused elements of the table.
*
* There are also linked lists of entries with identical hash(ip_src). These
* allow cleaning up the table from ip_src<->mac_src associations that have
* become outdated and would cause sending out invalid ARP updates to the
* network. These are linked by the (src_next and src_prev members).
* -------------------------------------------------------------------------
*/
struct rlb_client_info {
__be32 ip_src; /* the server IP address */
__be32 ip_dst; /* the client IP address */
u8 mac_src[ETH_ALEN]; /* the server MAC address */
u8 mac_dst[ETH_ALEN]; /* the client MAC address */
/* list of used hash table entries, starting at rx_hashtbl_used_head */
u32 used_next;
u32 used_prev;
/* ip_src based hashing */
u32 src_next; /* next entry with same hash(ip_src) */
u32 src_prev; /* prev entry with same hash(ip_src) */
u32 src_first; /* first entry with hash(ip_src) == this entry's index */
u8 assigned; /* checking whether this entry is assigned */
u8 ntt; /* flag - need to transmit client info */
struct slave *slave; /* the slave assigned to this client */
unsigned short vlan_id; /* VLAN tag associated with IP address */
};
struct tlb_slave_info {
u32 head; /* Index to the head of the bi-directional clients
* hash table entries list. The entries in the list
* are the entries that were assigned to use this
* slave for transmit.
*/
u32 load; /* Each slave sums the loadHistory of all clients
* assigned to it
*/
};
struct alb_bond_info {
struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
u32 unbalanced_load;
int tx_rebalance_counter;
int lp_counter;
/* -------- rlb parameters -------- */
int rlb_enabled;
struct rlb_client_info *rx_hashtbl; /* Receive hash table */
u32 rx_hashtbl_used_head;
u8 rx_ntt; /* flag - need to transmit
* to all rx clients
*/
struct slave *rx_slave;/* last slave to xmit from */
u8 primary_is_promisc; /* boolean */
u32 rlb_promisc_timeout_counter;/* counts primary
* promiscuity time
*/
u32 rlb_update_delay_counter;
u32 rlb_update_retry_counter;/* counter of retries
* of client update
*/
u8 rlb_rebalance; /* flag - indicates that the
* rx traffic should be
* rebalanced
*/
};
int bond_alb_initialize(struct bonding *bond, int rlb_enabled);
void bond_alb_deinitialize(struct bonding *bond);
int bond_alb_init_slave(struct bonding *bond, struct slave *slave);
void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave);
void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link);
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave);
int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
void bond_alb_monitor(struct work_struct *);
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
#endif /* _NET_BOND_ALB_H */
+136
View File
@@ -0,0 +1,136 @@
/*
* drivers/net/bond/bond_options.h - bonding options
* Copyright (c) 2013 Nikolay Aleksandrov <nikolay@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _NET_BOND_OPTIONS_H
#define _NET_BOND_OPTIONS_H
#define BOND_OPT_MAX_NAMELEN 32
#define BOND_OPT_VALID(opt) ((opt) < BOND_OPT_LAST)
#define BOND_MODE_ALL_EX(x) (~(x))
/* Option flags:
* BOND_OPTFLAG_NOSLAVES - check if the bond device is empty before setting
* BOND_OPTFLAG_IFDOWN - check if the bond device is down before setting
* BOND_OPTFLAG_RAWVAL - the option parses the value itself
*/
enum {
BOND_OPTFLAG_NOSLAVES = BIT(0),
BOND_OPTFLAG_IFDOWN = BIT(1),
BOND_OPTFLAG_RAWVAL = BIT(2)
};
/* Value type flags:
* BOND_VALFLAG_DEFAULT - mark the value as default
* BOND_VALFLAG_(MIN|MAX) - mark the value as min/max
*/
enum {
BOND_VALFLAG_DEFAULT = BIT(0),
BOND_VALFLAG_MIN = BIT(1),
BOND_VALFLAG_MAX = BIT(2)
};
/* Option IDs, their bit positions correspond to their IDs */
enum {
BOND_OPT_MODE,
BOND_OPT_PACKETS_PER_SLAVE,
BOND_OPT_XMIT_HASH,
BOND_OPT_ARP_VALIDATE,
BOND_OPT_ARP_ALL_TARGETS,
BOND_OPT_FAIL_OVER_MAC,
BOND_OPT_ARP_INTERVAL,
BOND_OPT_ARP_TARGETS,
BOND_OPT_DOWNDELAY,
BOND_OPT_UPDELAY,
BOND_OPT_LACP_RATE,
BOND_OPT_MINLINKS,
BOND_OPT_AD_SELECT,
BOND_OPT_NUM_PEER_NOTIF,
BOND_OPT_MIIMON,
BOND_OPT_PRIMARY,
BOND_OPT_PRIMARY_RESELECT,
BOND_OPT_USE_CARRIER,
BOND_OPT_ACTIVE_SLAVE,
BOND_OPT_QUEUE_ID,
BOND_OPT_ALL_SLAVES_ACTIVE,
BOND_OPT_RESEND_IGMP,
BOND_OPT_LP_INTERVAL,
BOND_OPT_SLAVES,
BOND_OPT_TLB_DYNAMIC_LB,
BOND_OPT_AD_ACTOR_SYS_PRIO,
BOND_OPT_AD_ACTOR_SYSTEM,
BOND_OPT_AD_USER_PORT_KEY,
BOND_OPT_NUM_PEER_NOTIF_ALIAS,
BOND_OPT_LAST
};
/* This structure is used for storing option values and for passing option
* values when changing an option. The logic when used as an arg is as follows:
* - if string != NULL -> parse it, if the opt is RAW type then return it, else
* return the parse result
* - if string == NULL -> parse value
*/
struct bond_opt_value {
char *string;
u64 value;
u32 flags;
};
struct bonding;
struct bond_option {
int id;
const char *name;
const char *desc;
u32 flags;
/* unsuppmodes is used to denote modes in which the option isn't
* supported.
*/
unsigned long unsuppmodes;
/* supported values which this option can have, can be a subset of
* BOND_OPTVAL_RANGE's value range
*/
const struct bond_opt_value *values;
int (*set)(struct bonding *bond, const struct bond_opt_value *val);
};
int __bond_opt_set(struct bonding *bond, unsigned int option,
struct bond_opt_value *val);
int __bond_opt_set_notify(struct bonding *bond, unsigned int option,
struct bond_opt_value *val);
int bond_opt_tryset_rtnl(struct bonding *bond, unsigned int option, char *buf);
const struct bond_opt_value *bond_opt_parse(const struct bond_option *opt,
struct bond_opt_value *val);
const struct bond_option *bond_opt_get(unsigned int option);
const struct bond_option *bond_opt_get_by_name(const char *name);
const struct bond_opt_value *bond_opt_get_val(unsigned int option, u64 val);
/* This helper is used to initialize a bond_opt_value structure for parameter
* passing. There should be either a valid string or value, but not both.
* When value is ULLONG_MAX then string will be used.
*/
static inline void __bond_opt_init(struct bond_opt_value *optval,
char *string, u64 value)
{
memset(optval, 0, sizeof(*optval));
optval->value = ULLONG_MAX;
if (value == ULLONG_MAX)
optval->string = string;
else
optval->value = value;
}
#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value)
#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX)
void bond_option_arp_ip_targets_clear(struct bonding *bond);
#endif /* _NET_BOND_OPTIONS_H */
+750
View File
@@ -0,0 +1,750 @@
/*
* Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
*
* Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
* NCM: Network and Communications Management, Inc.
*
* BUT, I'm the one who modified it for ethernet, so:
* (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
*
* This software may be used and distributed according to the terms
* of the GNU Public License, incorporated herein by reference.
*
*/
#ifndef _NET_BONDING_H
#define _NET_BONDING_H
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
#include <linux/cpumask.h>
#include <linux/in6.h>
#include <linux/netpoll.h>
#include <linux/inetdevice.h>
#include <linux/etherdevice.h>
#include <linux/reciprocal_div.h>
#include <linux/if_link.h>
#include <net/bond_3ad.h>
#include <net/bond_alb.h>
#include <net/bond_options.h>
#define BOND_MAX_ARP_TARGETS 16
#define BOND_DEFAULT_MIIMON 100
#ifndef __long_aligned
#define __long_aligned __attribute__((aligned((sizeof(long)))))
#endif
#define BOND_MODE(bond) ((bond)->params.mode)
/* slave list primitives */
#define bond_slave_list(bond) (&(bond)->dev->adj_list.lower)
#define bond_has_slaves(bond) !list_empty(bond_slave_list(bond))
/* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
#define bond_first_slave(bond) \
(bond_has_slaves(bond) ? \
netdev_adjacent_get_private(bond_slave_list(bond)->next) : \
NULL)
#define bond_last_slave(bond) \
(bond_has_slaves(bond) ? \
netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \
NULL)
/* Caller must have rcu_read_lock */
#define bond_first_slave_rcu(bond) \
netdev_lower_get_first_private_rcu(bond->dev)
#define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond))
#define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))
/**
* bond_for_each_slave - iterate over all slaves
* @bond: the bond holding this list
* @pos: current slave
* @iter: list_head * iterator
*
* Caller must hold RTNL
*/
#define bond_for_each_slave(bond, pos, iter) \
netdev_for_each_lower_private((bond)->dev, pos, iter)
/* Caller must have rcu_read_lock */
#define bond_for_each_slave_rcu(bond, pos, iter) \
netdev_for_each_lower_private_rcu((bond)->dev, pos, iter)
#ifdef CONFIG_NET_POLL_CONTROLLER
extern atomic_t netpoll_block_tx;
static inline void block_netpoll_tx(void)
{
atomic_inc(&netpoll_block_tx);
}
static inline void unblock_netpoll_tx(void)
{
atomic_dec(&netpoll_block_tx);
}
static inline int is_netpoll_tx_blocked(struct net_device *dev)
{
if (unlikely(netpoll_tx_running(dev)))
return atomic_read(&netpoll_block_tx);
return 0;
}
#else
#define block_netpoll_tx()
#define unblock_netpoll_tx()
#define is_netpoll_tx_blocked(dev) (0)
#endif
struct bond_params {
int mode;
int xmit_policy;
int miimon;
u8 num_peer_notif;
int arp_interval;
int arp_validate;
int arp_all_targets;
int use_carrier;
int fail_over_mac;
int updelay;
int downdelay;
int lacp_fast;
unsigned int min_links;
int ad_select;
char primary[IFNAMSIZ];
int primary_reselect;
__be32 arp_targets[BOND_MAX_ARP_TARGETS];
int tx_queues;
int all_slaves_active;
int resend_igmp;
int lp_interval;
int packets_per_slave;
int tlb_dynamic_lb;
struct reciprocal_value reciprocal_packets_per_slave;
u16 ad_actor_sys_prio;
u16 ad_user_port_key;
/* 2 bytes of padding : see ether_addr_equal_64bits() */
u8 ad_actor_system[ETH_ALEN + 2];
};
struct bond_parm_tbl {
char *modename;
int mode;
};
struct slave {
struct net_device *dev; /* first - useful for panic debug */
struct bonding *bond; /* our master */
int delay;
/* all three in jiffies */
unsigned long last_link_up;
unsigned long last_rx;
unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS];
s8 link; /* one of BOND_LINK_XXXX */
s8 link_new_state; /* one of BOND_LINK_XXXX */
u8 backup:1, /* indicates backup slave. Value corresponds with
BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
inactive:1, /* indicates inactive slave */
should_notify:1, /* indicates whether the state changed */
should_notify_link:1; /* indicates whether the link changed */
u8 duplex;
u32 original_mtu;
u32 link_failure_count;
u32 speed;
u16 queue_id;
u8 perm_hwaddr[MAX_ADDR_LEN];
struct ad_slave_info *ad_info;
struct tlb_slave_info tlb_info;
#ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *np;
#endif
struct delayed_work notify_work;
struct kobject kobj;
struct rtnl_link_stats64 slave_stats;
};
static inline struct slave *to_slave(struct kobject *kobj)
{
return container_of(kobj, struct slave, kobj);
}
struct bond_up_slave {
unsigned int count;
struct rcu_head rcu;
struct slave *arr[0];
};
/*
* Link pseudo-state only used internally by monitors
*/
#define BOND_LINK_NOCHANGE -1
/*
* Here are the locking policies for the two bonding locks:
* Get rcu_read_lock when reading or RTNL when writing slave list.
*/
struct bonding {
struct net_device *dev; /* first - useful for panic debug */
struct slave __rcu *curr_active_slave;
struct slave __rcu *current_arp_slave;
struct slave __rcu *primary_slave;
struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
bool force_primary;
u32 nest_level;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
int (*recv_probe)(const struct sk_buff *, struct bonding *,
struct slave *);
/* mode_lock is used for mode-specific locking needs, currently used by:
* 3ad mode (4) - protect against running bond_3ad_unbind_slave() and
* bond_3ad_state_machine_handler() concurrently and also
* the access to the state machine shared variables.
* TLB mode (5) - to sync the use and modifications of its hash table
* ALB mode (6) - to sync the use and modifications of its hash table
*/
spinlock_t mode_lock;
spinlock_t stats_lock;
u8 send_peer_notif;
u8 igmp_retrans;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
char proc_file_name[IFNAMSIZ];
#endif /* CONFIG_PROC_FS */
struct list_head bond_list;
u32 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
struct bond_params params;
struct workqueue_struct *wq;
struct delayed_work mii_work;
struct delayed_work arp_work;
struct delayed_work alb_work;
struct delayed_work ad_work;
struct delayed_work mcast_work;
struct delayed_work slave_arr_work;
#ifdef CONFIG_DEBUG_FS
/* debugging support via debugfs */
struct dentry *debug_dir;
#endif /* CONFIG_DEBUG_FS */
struct rtnl_link_stats64 bond_stats;
};
#define bond_slave_get_rcu(dev) \
((struct slave *) rcu_dereference(dev->rx_handler_data))
#define bond_slave_get_rtnl(dev) \
((struct slave *) rtnl_dereference(dev->rx_handler_data))
void bond_queue_slave_event(struct slave *slave);
void bond_lower_state_changed(struct slave *slave);
struct bond_vlan_tag {
__be16 vlan_proto;
unsigned short vlan_id;
};
/**
* Returns NULL if the net_device does not belong to any of the bond's slaves
*
* Caller must hold bond lock for read
*/
static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
struct net_device *slave_dev)
{
return netdev_lower_dev_get_private(bond->dev, slave_dev);
}
static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
{
return slave->bond;
}
static inline bool bond_should_override_tx_queue(struct bonding *bond)
{
return BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP ||
BOND_MODE(bond) == BOND_MODE_ROUNDROBIN;
}
static inline bool bond_is_lb(const struct bonding *bond)
{
return BOND_MODE(bond) == BOND_MODE_TLB ||
BOND_MODE(bond) == BOND_MODE_ALB;
}
static inline bool bond_needs_speed_duplex(const struct bonding *bond)
{
return BOND_MODE(bond) == BOND_MODE_8023AD || bond_is_lb(bond);
}
static inline bool bond_is_nondyn_tlb(const struct bonding *bond)
{
return (bond_is_lb(bond) && bond->params.tlb_dynamic_lb == 0);
}
static inline bool bond_mode_can_use_xmit_hash(const struct bonding *bond)
{
return (BOND_MODE(bond) == BOND_MODE_8023AD ||
BOND_MODE(bond) == BOND_MODE_XOR ||
BOND_MODE(bond) == BOND_MODE_TLB ||
BOND_MODE(bond) == BOND_MODE_ALB);
}
static inline bool bond_mode_uses_xmit_hash(const struct bonding *bond)
{
return (BOND_MODE(bond) == BOND_MODE_8023AD ||
BOND_MODE(bond) == BOND_MODE_XOR ||
bond_is_nondyn_tlb(bond));
}
static inline bool bond_mode_uses_arp(int mode)
{
return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB &&
mode != BOND_MODE_ALB;
}
static inline bool bond_mode_uses_primary(int mode)
{
return mode == BOND_MODE_ACTIVEBACKUP || mode == BOND_MODE_TLB ||
mode == BOND_MODE_ALB;
}
static inline bool bond_uses_primary(struct bonding *bond)
{
return bond_mode_uses_primary(BOND_MODE(bond));
}
static inline struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond)
{
struct slave *slave = rcu_dereference(bond->curr_active_slave);
return bond_uses_primary(bond) && slave ? slave->dev : NULL;
}
static inline bool bond_slave_is_up(struct slave *slave)
{
return netif_running(slave->dev) && netif_carrier_ok(slave->dev);
}
static inline void bond_set_active_slave(struct slave *slave)
{
if (slave->backup) {
slave->backup = 0;
bond_queue_slave_event(slave);
bond_lower_state_changed(slave);
}
}
static inline void bond_set_backup_slave(struct slave *slave)
{
if (!slave->backup) {
slave->backup = 1;
bond_queue_slave_event(slave);
bond_lower_state_changed(slave);
}
}
static inline void bond_set_slave_state(struct slave *slave,
int slave_state, bool notify)
{
if (slave->backup == slave_state)
return;
slave->backup = slave_state;
if (notify) {
bond_lower_state_changed(slave);
bond_queue_slave_event(slave);
slave->should_notify = 0;
} else {
if (slave->should_notify)
slave->should_notify = 0;
else
slave->should_notify = 1;
}
}
static inline void bond_slave_state_change(struct bonding *bond)
{
struct list_head *iter;
struct slave *tmp;
bond_for_each_slave(bond, tmp, iter) {
if (tmp->link == BOND_LINK_UP)
bond_set_active_slave(tmp);
else if (tmp->link == BOND_LINK_DOWN)
bond_set_backup_slave(tmp);
}
}
static inline void bond_slave_state_notify(struct bonding *bond)
{
struct list_head *iter;
struct slave *tmp;
bond_for_each_slave(bond, tmp, iter) {
if (tmp->should_notify) {
bond_lower_state_changed(tmp);
tmp->should_notify = 0;
}
}
}
static inline int bond_slave_state(struct slave *slave)
{
return slave->backup;
}
static inline bool bond_is_active_slave(struct slave *slave)
{
return !bond_slave_state(slave);
}
static inline bool bond_slave_can_tx(struct slave *slave)
{
return bond_slave_is_up(slave) && slave->link == BOND_LINK_UP &&
bond_is_active_slave(slave);
}
static inline bool bond_is_active_slave_dev(const struct net_device *slave_dev)
{
struct slave *slave;
bool active;
rcu_read_lock();
slave = bond_slave_get_rcu(slave_dev);
active = bond_is_active_slave(slave);
rcu_read_unlock();
return active;
}
static inline void bond_hw_addr_copy(u8 *dst, const u8 *src, unsigned int len)
{
if (len == ETH_ALEN) {
ether_addr_copy(dst, src);
return;
}
memcpy(dst, src, len);
}
#define BOND_PRI_RESELECT_ALWAYS 0
#define BOND_PRI_RESELECT_BETTER 1
#define BOND_PRI_RESELECT_FAILURE 2
#define BOND_FOM_NONE 0
#define BOND_FOM_ACTIVE 1
#define BOND_FOM_FOLLOW 2
#define BOND_ARP_TARGETS_ANY 0
#define BOND_ARP_TARGETS_ALL 1
#define BOND_ARP_VALIDATE_NONE 0
#define BOND_ARP_VALIDATE_ACTIVE (1 << BOND_STATE_ACTIVE)
#define BOND_ARP_VALIDATE_BACKUP (1 << BOND_STATE_BACKUP)
#define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \
BOND_ARP_VALIDATE_BACKUP)
#define BOND_ARP_FILTER (BOND_ARP_VALIDATE_ALL + 1)
#define BOND_ARP_FILTER_ACTIVE (BOND_ARP_VALIDATE_ACTIVE | \
BOND_ARP_FILTER)
#define BOND_ARP_FILTER_BACKUP (BOND_ARP_VALIDATE_BACKUP | \
BOND_ARP_FILTER)
#define BOND_SLAVE_NOTIFY_NOW true
#define BOND_SLAVE_NOTIFY_LATER false
static inline int slave_do_arp_validate(struct bonding *bond,
struct slave *slave)
{
return bond->params.arp_validate & (1 << bond_slave_state(slave));
}
static inline int slave_do_arp_validate_only(struct bonding *bond)
{
return bond->params.arp_validate & BOND_ARP_FILTER;
}
static inline int bond_is_ip_target_ok(__be32 addr)
{
return !ipv4_is_lbcast(addr) && !ipv4_is_zeronet(addr);
}
/* Get the oldest arp which we've received on this slave for bond's
* arp_targets.
*/
static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond,
struct slave *slave)
{
int i = 1;
unsigned long ret = slave->target_last_arp_rx[0];
for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++)
if (time_before(slave->target_last_arp_rx[i], ret))
ret = slave->target_last_arp_rx[i];
return ret;
}
static inline unsigned long slave_last_rx(struct bonding *bond,
struct slave *slave)
{
if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL)
return slave_oldest_target_arp_rx(bond, slave);
return slave->last_rx;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
static inline void bond_netpoll_send_skb(const struct slave *slave,
struct sk_buff *skb)
{
struct netpoll *np = slave->np;
if (np)
netpoll_send_skb(np, skb);
}
#else
static inline void bond_netpoll_send_skb(const struct slave *slave,
struct sk_buff *skb)
{
}
#endif
static inline void bond_set_slave_inactive_flags(struct slave *slave,
bool notify)
{
if (!bond_is_lb(slave->bond))
bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);
if (!slave->bond->params.all_slaves_active)
slave->inactive = 1;
}
static inline void bond_set_slave_active_flags(struct slave *slave,
bool notify)
{
bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify);
slave->inactive = 0;
}
static inline bool bond_is_slave_inactive(struct slave *slave)
{
return slave->inactive;
}
static inline void bond_propose_link_state(struct slave *slave, int state)
{
slave->link_new_state = state;
}
static inline void bond_commit_link_state(struct slave *slave, bool notify)
{
if (slave->link_new_state == BOND_LINK_NOCHANGE)
return;
slave->link = slave->link_new_state;
if (notify) {
bond_queue_slave_event(slave);
bond_lower_state_changed(slave);
slave->should_notify_link = 0;
} else {
if (slave->should_notify_link)
slave->should_notify_link = 0;
else
slave->should_notify_link = 1;
}
}
static inline void bond_set_slave_link_state(struct slave *slave, int state,
bool notify)
{
bond_propose_link_state(slave, state);
bond_commit_link_state(slave, notify);
}
static inline void bond_slave_link_notify(struct bonding *bond)
{
struct list_head *iter;
struct slave *tmp;
bond_for_each_slave(bond, tmp, iter) {
if (tmp->should_notify_link) {
bond_queue_slave_event(tmp);
bond_lower_state_changed(tmp);
tmp->should_notify_link = 0;
}
}
}
static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be32 local)
{
struct in_device *in_dev;
__be32 addr = 0;
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
if (in_dev)
addr = inet_confirm_addr(dev_net(dev), in_dev, dst, local,
RT_SCOPE_HOST);
rcu_read_unlock();
return addr;
}
struct bond_net {
struct net *net; /* Associated network namespace */
struct list_head dev_list;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_dir;
#endif
struct class_attribute class_attr_bonding_masters;
};
int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave);
void bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(struct net *net, const char *name);
int bond_create_sysfs(struct bond_net *net);
void bond_destroy_sysfs(struct bond_net *net);
void bond_prepare_sysfs_group(struct bonding *bond);
int bond_sysfs_slave_add(struct slave *slave);
void bond_sysfs_slave_del(struct slave *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
struct netlink_ext_ack *extack);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb);
int bond_set_carrier(struct bonding *bond);
void bond_select_active_slave(struct bonding *bond);
void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
void bond_create_debugfs(void);
void bond_destroy_debugfs(void);
void bond_debug_register(struct bonding *bond);
void bond_debug_unregister(struct bonding *bond);
void bond_debug_reregister(struct bonding *bond);
const char *bond_mode_name(int mode);
void bond_setup(struct net_device *bond_dev);
unsigned int bond_get_num_tx_queues(void);
int bond_netlink_init(void);
void bond_netlink_fini(void);
struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
const char *bond_slave_link_status(s8 link);
struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
struct net_device *end_dev,
int level);
int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave);
void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay);
void bond_work_init_all(struct bonding *bond);
#ifdef CONFIG_PROC_FS
void bond_create_proc_entry(struct bonding *bond);
void bond_remove_proc_entry(struct bonding *bond);
void bond_create_proc_dir(struct bond_net *bn);
void bond_destroy_proc_dir(struct bond_net *bn);
#else
static inline void bond_create_proc_entry(struct bonding *bond)
{
}
static inline void bond_remove_proc_entry(struct bonding *bond)
{
}
static inline void bond_create_proc_dir(struct bond_net *bn)
{
}
static inline void bond_destroy_proc_dir(struct bond_net *bn)
{
}
#endif
static inline struct slave *bond_slave_has_mac(struct bonding *bond,
const u8 *mac)
{
struct list_head *iter;
struct slave *tmp;
bond_for_each_slave(bond, tmp, iter)
if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
return tmp;
return NULL;
}
/* Caller must hold rcu_read_lock() for read */
static inline struct slave *bond_slave_has_mac_rcu(struct bonding *bond,
const u8 *mac)
{
struct list_head *iter;
struct slave *tmp;
bond_for_each_slave_rcu(bond, tmp, iter)
if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
return tmp;
return NULL;
}
/* Caller must hold rcu_read_lock() for read */
static inline bool bond_slave_has_mac_rx(struct bonding *bond, const u8 *mac)
{
struct list_head *iter;
struct slave *tmp;
struct netdev_hw_addr *ha;
bond_for_each_slave_rcu(bond, tmp, iter)
if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
return true;
if (netdev_uc_empty(bond->dev))
return false;
netdev_for_each_uc_addr(ha, bond->dev)
if (ether_addr_equal_64bits(mac, ha->addr))
return true;
return false;
}
/* Check if the ip is present in arp ip list, or first free slot if ip == 0
* Returns -1 if not found, index if found
*/
static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
{
int i;
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
if (targets[i] == ip)
return i;
else if (targets[i] == 0)
break;
return -1;
}
/* exported from bond_main.c */
extern unsigned int bond_net_id;
extern const struct bond_parm_tbl bond_lacp_tbl[];
extern const struct bond_parm_tbl xmit_hashtype_tbl[];
extern const struct bond_parm_tbl arp_validate_tbl[];
extern const struct bond_parm_tbl arp_all_targets_tbl[];
extern const struct bond_parm_tbl fail_over_mac_tbl[];
extern const struct bond_parm_tbl pri_reselect_tbl[];
extern struct bond_parm_tbl ad_select_tbl[];
/* exported from bond_netlink.c */
extern struct rtnl_link_ops bond_link_ops;
/* exported from bond_sysfs_slave.c */
extern const struct sysfs_ops slave_sysfs_ops;
static inline void bond_tx_drop(struct net_device *dev, struct sk_buff *skb)
{
atomic_long_inc(&dev->tx_dropped);
dev_kfree_skb_any(skb);
}
#endif /* _NET_BONDING_H */
+152
View File
@@ -0,0 +1,152 @@
/*
* net busy poll support
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Author: Eliezer Tamir
*
* Contact Information:
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
*/
#ifndef _LINUX_NET_BUSY_POLL_H
#define _LINUX_NET_BUSY_POLL_H
#include <linux/netdevice.h>
#include <linux/sched/clock.h>
#include <linux/sched/signal.h>
#include <net/ip.h>
/* 0 - Reserved to indicate value not set
* 1..NR_CPUS - Reserved for sender_cpu
* NR_CPUS+1..~0 - Region available for NAPI IDs
*/
#define MIN_NAPI_ID ((unsigned int)(NR_CPUS + 1))
#ifdef CONFIG_NET_RX_BUSY_POLL
struct napi_struct;
extern unsigned int sysctl_net_busy_read __read_mostly;
extern unsigned int sysctl_net_busy_poll __read_mostly;
static inline bool net_busy_loop_on(void)
{
return sysctl_net_busy_poll;
}
static inline bool sk_can_busy_loop(const struct sock *sk)
{
return sk->sk_ll_usec && !signal_pending(current);
}
bool sk_busy_loop_end(void *p, unsigned long start_time);
void napi_busy_loop(unsigned int napi_id,
bool (*loop_end)(void *, unsigned long),
void *loop_end_arg);
#else /* CONFIG_NET_RX_BUSY_POLL */
static inline unsigned long net_busy_loop_on(void)
{
return 0;
}
static inline bool sk_can_busy_loop(struct sock *sk)
{
return false;
}
#endif /* CONFIG_NET_RX_BUSY_POLL */
static inline unsigned long busy_loop_current_time(void)
{
#ifdef CONFIG_NET_RX_BUSY_POLL
return (unsigned long)(local_clock() >> 10);
#else
return 0;
#endif
}
/* in poll/select we use the global sysctl_net_ll_poll value */
static inline bool busy_loop_timeout(unsigned long start_time)
{
#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned long bp_usec = READ_ONCE(sysctl_net_busy_poll);
if (bp_usec) {
unsigned long end_time = start_time + bp_usec;
unsigned long now = busy_loop_current_time();
return time_after(now, end_time);
}
#endif
return true;
}
static inline bool sk_busy_loop_timeout(struct sock *sk,
unsigned long start_time)
{
#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned long bp_usec = READ_ONCE(sk->sk_ll_usec);
if (bp_usec) {
unsigned long end_time = start_time + bp_usec;
unsigned long now = busy_loop_current_time();
return time_after(now, end_time);
}
#endif
return true;
}
static inline void sk_busy_loop(struct sock *sk, int nonblock)
{
#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned int napi_id = READ_ONCE(sk->sk_napi_id);
if (napi_id >= MIN_NAPI_ID)
napi_busy_loop(napi_id, nonblock ? NULL : sk_busy_loop_end, sk);
#endif
}
/* used in the NIC receive handler to mark the skb */
static inline void skb_mark_napi_id(struct sk_buff *skb,
struct napi_struct *napi)
{
#ifdef CONFIG_NET_RX_BUSY_POLL
skb->napi_id = napi->napi_id;
#endif
}
/* used in the protocol hanlder to propagate the napi_id to the socket */
static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb)
{
#ifdef CONFIG_NET_RX_BUSY_POLL
WRITE_ONCE(sk->sk_napi_id, skb->napi_id);
#endif
sk_rx_queue_set(sk, skb);
}
/* variant used for unconnected sockets */
static inline void sk_mark_napi_id_once(struct sock *sk,
const struct sk_buff *skb)
{
#ifdef CONFIG_NET_RX_BUSY_POLL
if (!READ_ONCE(sk->sk_napi_id))
WRITE_ONCE(sk->sk_napi_id, skb->napi_id);
#endif
}
#endif /* _LINUX_NET_BUSY_POLL_H */
+128
View File
@@ -0,0 +1,128 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_DEV_H_
#define CAIF_DEV_H_
#include <net/caif/caif_layer.h>
#include <net/caif/cfcnfg.h>
#include <net/caif/caif_device.h>
#include <linux/caif/caif_socket.h>
#include <linux/if.h>
#include <linux/net.h>
/**
* struct caif_param - CAIF parameters.
* @size: Length of data
* @data: Binary Data Blob
*/
struct caif_param {
u16 size;
u8 data[256];
};
/**
* struct caif_connect_request - Request data for CAIF channel setup.
* @protocol: Type of CAIF protocol to use (at, datagram etc)
* @sockaddr: Socket address to connect.
* @priority: Priority of the connection.
* @link_selector: Link selector (high bandwidth or low latency)
* @ifindex: kernel index of the interface.
* @param: Connect Request parameters (CAIF_SO_REQ_PARAM).
*
* This struct is used when connecting a CAIF channel.
* It contains all CAIF channel configuration options.
*/
struct caif_connect_request {
enum caif_protocol_type protocol;
struct sockaddr_caif sockaddr;
enum caif_channel_priority priority;
enum caif_link_selector link_selector;
int ifindex;
struct caif_param param;
};
/**
* caif_connect_client - Connect a client to CAIF Core Stack.
* @config: Channel setup parameters, specifying what address
* to connect on the Modem.
* @client_layer: User implementation of client layer. This layer
* MUST have receive and control callback functions
* implemented.
* @ifindex: Link layer interface index used for this connection.
* @headroom: Head room needed by CAIF protocol.
* @tailroom: Tail room needed by CAIF protocol.
*
* This function connects a CAIF channel. The Client must implement
* the struct cflayer. This layer represents the Client layer and holds
* receive functions and control callback functions. Control callback
* function will receive information about connect/disconnect responses,
* flow control etc (see enum caif_control).
* E.g. CAIF Socket will call this function for each socket it connects
* and have one client_layer instance for each socket.
*/
int caif_connect_client(struct net *net,
struct caif_connect_request *conn_req,
struct cflayer *client_layer, int *ifindex,
int *headroom, int *tailroom);
/**
* caif_disconnect_client - Disconnects a client from the CAIF stack.
*
* @client_layer: Client layer to be disconnected.
*/
int caif_disconnect_client(struct net *net, struct cflayer *client_layer);
/**
* caif_client_register_refcnt - register ref-count functions provided by client.
*
* @adapt_layer: Client layer using CAIF Stack.
* @hold: Function provided by client layer increasing ref-count
* @put: Function provided by client layer decreasing ref-count
*
* Client of the CAIF Stack must register functions for reference counting.
* These functions are called by the CAIF Stack for every upstream packet,
* and must therefore be implemented efficiently.
*
* Client should call caif_free_client when reference count degrease to zero.
*/
void caif_client_register_refcnt(struct cflayer *adapt_layer,
void (*hold)(struct cflayer *lyr),
void (*put)(struct cflayer *lyr));
/**
* caif_free_client - Free memory used to manage the client in the CAIF Stack.
*
* @client_layer: Client layer to be removed.
*
* This function must be called from client layer in order to free memory.
* Caller must guarantee that no packets are in flight upstream when calling
* this function.
*/
void caif_free_client(struct cflayer *adap_layer);
/**
* struct caif_enroll_dev - Enroll a net-device as a CAIF Link layer
* @dev: Network device to enroll.
* @caifdev: Configuration information from CAIF Link Layer
* @link_support: Link layer support layer
* @head_room: Head room needed by link support layer
* @layer: Lowest layer in CAIF stack
* @rcv_fun: Receive function for CAIF stack.
*
* This function enroll a CAIF link layer into CAIF Stack and
* expects the interface to be able to handle CAIF payload.
* The link_support layer is used to add any Link Layer specific
* framing.
*/
void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
struct cflayer *link_support, int head_room,
struct cflayer **layer, int (**rcv_func)(
struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *));
#endif /* CAIF_DEV_H_ */
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_DEVICE_H_
#define CAIF_DEVICE_H_
#include <linux/kernel.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/caif/caif_socket.h>
#include <net/caif/caif_device.h>
/**
* struct caif_dev_common - data shared between CAIF drivers and stack.
* @flowctrl: Flow Control callback function. This function is
* supplied by CAIF Core Stack and is used by CAIF
* Link Layer to send flow-stop to CAIF Core.
* The flow information will be distributed to all
* clients of CAIF.
*
* @link_select: Profile of device, either high-bandwidth or
* low-latency. This member is set by CAIF Link
* Layer Device in order to indicate if this device
* is a high bandwidth or low latency device.
*
* @use_frag: CAIF Frames may be fragmented.
* Is set by CAIF Link Layer in order to indicate if the
* interface receives fragmented frames that must be
* assembled by CAIF Core Layer.
*
* @use_fcs: Indicate if Frame CheckSum (fcs) is used.
* Is set if the physical interface is
* using Frame Checksum on the CAIF Frames.
*
* @use_stx: Indicate STart of frame eXtension (stx) in use.
* Is set if the CAIF Link Layer expects
* CAIF Frames to start with the STX byte.
*
* This structure is shared between the CAIF drivers and the CAIF stack.
* It is used by the device to register its behavior.
* CAIF Core layer must set the member flowctrl in order to supply
* CAIF Link Layer with the flow control function.
*
*/
struct caif_dev_common {
void (*flowctrl)(struct net_device *net, int on);
enum caif_link_selector link_select;
int use_frag;
int use_fcs;
int use_stx;
};
#endif /* CAIF_DEVICE_H_ */
+200
View File
@@ -0,0 +1,200 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Daniel Martensson / daniel.martensson@stericsson.com
* Dmitry.Tarnyagin / dmitry.tarnyagin@stericsson.com
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_HSI_H_
#define CAIF_HSI_H_
#include <net/caif/caif_layer.h>
#include <net/caif/caif_device.h>
#include <linux/atomic.h>
/*
* Maximum number of CAIF frames that can reside in the same HSI frame.
*/
#define CFHSI_MAX_PKTS 15
/*
* Maximum number of bytes used for the frame that can be embedded in the
* HSI descriptor.
*/
#define CFHSI_MAX_EMB_FRM_SZ 96
/*
* Decides if HSI buffers should be prefilled with 0xFF pattern for easier
* debugging. Both TX and RX buffers will be filled before the transfer.
*/
#define CFHSI_DBG_PREFILL 0
/* Structure describing a HSI packet descriptor. */
#pragma pack(1) /* Byte alignment. */
struct cfhsi_desc {
u8 header;
u8 offset;
u16 cffrm_len[CFHSI_MAX_PKTS];
u8 emb_frm[CFHSI_MAX_EMB_FRM_SZ];
};
#pragma pack() /* Default alignment. */
/* Size of the complete HSI packet descriptor. */
#define CFHSI_DESC_SZ (sizeof(struct cfhsi_desc))
/*
* Size of the complete HSI packet descriptor excluding the optional embedded
* CAIF frame.
*/
#define CFHSI_DESC_SHORT_SZ (CFHSI_DESC_SZ - CFHSI_MAX_EMB_FRM_SZ)
/*
* Maximum bytes transferred in one transfer.
*/
#define CFHSI_MAX_CAIF_FRAME_SZ 4096
#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * CFHSI_MAX_CAIF_FRAME_SZ)
/* Size of the complete HSI TX buffer. */
#define CFHSI_BUF_SZ_TX (CFHSI_DESC_SZ + CFHSI_MAX_PAYLOAD_SZ)
/* Size of the complete HSI RX buffer. */
#define CFHSI_BUF_SZ_RX ((2 * CFHSI_DESC_SZ) + CFHSI_MAX_PAYLOAD_SZ)
/* Bitmasks for the HSI descriptor. */
#define CFHSI_PIGGY_DESC (0x01 << 7)
#define CFHSI_TX_STATE_IDLE 0
#define CFHSI_TX_STATE_XFER 1
#define CFHSI_RX_STATE_DESC 0
#define CFHSI_RX_STATE_PAYLOAD 1
/* Bitmasks for power management. */
#define CFHSI_WAKE_UP 0
#define CFHSI_WAKE_UP_ACK 1
#define CFHSI_WAKE_DOWN_ACK 2
#define CFHSI_AWAKE 3
#define CFHSI_WAKELOCK_HELD 4
#define CFHSI_SHUTDOWN 5
#define CFHSI_FLUSH_FIFO 6
#ifndef CFHSI_INACTIVITY_TOUT
#define CFHSI_INACTIVITY_TOUT (1 * HZ)
#endif /* CFHSI_INACTIVITY_TOUT */
#ifndef CFHSI_WAKE_TOUT
#define CFHSI_WAKE_TOUT (3 * HZ)
#endif /* CFHSI_WAKE_TOUT */
#ifndef CFHSI_MAX_RX_RETRIES
#define CFHSI_MAX_RX_RETRIES (10 * HZ)
#endif
/* Structure implemented by the CAIF HSI driver. */
struct cfhsi_cb_ops {
void (*tx_done_cb) (struct cfhsi_cb_ops *drv);
void (*rx_done_cb) (struct cfhsi_cb_ops *drv);
void (*wake_up_cb) (struct cfhsi_cb_ops *drv);
void (*wake_down_cb) (struct cfhsi_cb_ops *drv);
};
/* Structure implemented by HSI device. */
struct cfhsi_ops {
int (*cfhsi_up) (struct cfhsi_ops *dev);
int (*cfhsi_down) (struct cfhsi_ops *dev);
int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_ops *dev);
int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_ops *dev);
int (*cfhsi_wake_up) (struct cfhsi_ops *dev);
int (*cfhsi_wake_down) (struct cfhsi_ops *dev);
int (*cfhsi_get_peer_wake) (struct cfhsi_ops *dev, bool *status);
int (*cfhsi_fifo_occupancy) (struct cfhsi_ops *dev, size_t *occupancy);
int (*cfhsi_rx_cancel)(struct cfhsi_ops *dev);
struct cfhsi_cb_ops *cb_ops;
};
/* Structure holds status of received CAIF frames processing */
struct cfhsi_rx_state {
int state;
int nfrms;
int pld_len;
int retries;
bool piggy_desc;
};
/* Priority mapping */
enum {
CFHSI_PRIO_CTL = 0,
CFHSI_PRIO_VI,
CFHSI_PRIO_VO,
CFHSI_PRIO_BEBK,
CFHSI_PRIO_LAST,
};
struct cfhsi_config {
u32 inactivity_timeout;
u32 aggregation_timeout;
u32 head_align;
u32 tail_align;
u32 q_high_mark;
u32 q_low_mark;
};
/* Structure implemented by CAIF HSI drivers. */
struct cfhsi {
struct caif_dev_common cfdev;
struct net_device *ndev;
struct platform_device *pdev;
struct sk_buff_head qhead[CFHSI_PRIO_LAST];
struct cfhsi_cb_ops cb_ops;
struct cfhsi_ops *ops;
int tx_state;
struct cfhsi_rx_state rx_state;
struct cfhsi_config cfg;
int rx_len;
u8 *rx_ptr;
u8 *tx_buf;
u8 *rx_buf;
u8 *rx_flip_buf;
spinlock_t lock;
int flow_off_sent;
struct list_head list;
struct work_struct wake_up_work;
struct work_struct wake_down_work;
struct work_struct out_of_sync_work;
struct workqueue_struct *wq;
wait_queue_head_t wake_up_wait;
wait_queue_head_t wake_down_wait;
wait_queue_head_t flush_fifo_wait;
struct timer_list inactivity_timer;
struct timer_list rx_slowpath_timer;
/* TX aggregation */
int aggregation_len;
struct timer_list aggregation_timer;
unsigned long bits;
};
extern struct platform_driver cfhsi_driver;
/**
* enum ifla_caif_hsi - CAIF HSI NetlinkRT parameters.
* @IFLA_CAIF_HSI_INACTIVITY_TOUT: Inactivity timeout before
* taking the HSI wakeline down, in milliseconds.
* When using RT Netlink to create, destroy or configure a CAIF HSI interface,
* enum ifla_caif_hsi is used to specify the configuration attributes.
*/
enum ifla_caif_hsi {
__IFLA_CAIF_HSI_UNSPEC,
__IFLA_CAIF_HSI_INACTIVITY_TOUT,
__IFLA_CAIF_HSI_AGGREGATION_TOUT,
__IFLA_CAIF_HSI_HEAD_ALIGN,
__IFLA_CAIF_HSI_TAIL_ALIGN,
__IFLA_CAIF_HSI_QHIGH_WATERMARK,
__IFLA_CAIF_HSI_QLOW_WATERMARK,
__IFLA_CAIF_HSI_MAX
};
struct cfhsi_ops *cfhsi_get_ops(void);
#endif /* CAIF_HSI_H_ */
+279
View File
@@ -0,0 +1,279 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_LAYER_H_
#define CAIF_LAYER_H_
#include <linux/list.h>
struct cflayer;
struct cfpkt;
struct cfpktq;
struct caif_payload_info;
struct caif_packet_funcs;
#define CAIF_LAYER_NAME_SZ 16
/**
* caif_assert() - Assert function for CAIF.
* @assert: expression to evaluate.
*
* This function will print a error message and a do WARN_ON if the
* assertion failes. Normally this will do a stack up at the current location.
*/
#define caif_assert(assert) \
do { \
if (!(assert)) { \
pr_err("caif:Assert detected:'%s'\n", #assert); \
WARN_ON(!(assert)); \
} \
} while (0)
/**
* enum caif_ctrlcmd - CAIF Stack Control Signaling sent in layer.ctrlcmd().
*
* @CAIF_CTRLCMD_FLOW_OFF_IND: Flow Control is OFF, transmit function
* should stop sending data
*
* @CAIF_CTRLCMD_FLOW_ON_IND: Flow Control is ON, transmit function
* can start sending data
*
* @CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: Remote end modem has decided to close
* down channel
*
* @CAIF_CTRLCMD_INIT_RSP: Called initially when the layer below
* has finished initialization
*
* @CAIF_CTRLCMD_DEINIT_RSP: Called when de-initialization is
* complete
*
* @CAIF_CTRLCMD_INIT_FAIL_RSP: Called if initialization fails
*
* @_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: CAIF Link layer temporarily cannot
* send more packets.
* @_CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: Called if CAIF Link layer is able
* to send packets again.
* @_CAIF_CTRLCMD_PHYIF_DOWN_IND: Called if CAIF Link layer is going
* down.
*
* These commands are sent upwards in the CAIF stack to the CAIF Client.
* They are used for signaling originating from the modem or CAIF Link Layer.
* These are either responses (*_RSP) or events (*_IND).
*/
enum caif_ctrlcmd {
CAIF_CTRLCMD_FLOW_OFF_IND,
CAIF_CTRLCMD_FLOW_ON_IND,
CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND,
CAIF_CTRLCMD_INIT_RSP,
CAIF_CTRLCMD_DEINIT_RSP,
CAIF_CTRLCMD_INIT_FAIL_RSP,
_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND,
_CAIF_CTRLCMD_PHYIF_FLOW_ON_IND,
_CAIF_CTRLCMD_PHYIF_DOWN_IND,
};
/**
* enum caif_modemcmd - Modem Control Signaling, sent from CAIF Client
* to the CAIF Link Layer or modem.
*
* @CAIF_MODEMCMD_FLOW_ON_REQ: Flow Control is ON, transmit function
* can start sending data.
*
* @CAIF_MODEMCMD_FLOW_OFF_REQ: Flow Control is OFF, transmit function
* should stop sending data.
*
* @_CAIF_MODEMCMD_PHYIF_USEFULL: Notify physical layer that it is in use
*
* @_CAIF_MODEMCMD_PHYIF_USELESS: Notify physical layer that it is
* no longer in use.
*
* These are requests sent 'downwards' in the stack.
* Flow ON, OFF can be indicated to the modem.
*/
enum caif_modemcmd {
CAIF_MODEMCMD_FLOW_ON_REQ = 0,
CAIF_MODEMCMD_FLOW_OFF_REQ = 1,
_CAIF_MODEMCMD_PHYIF_USEFULL = 3,
_CAIF_MODEMCMD_PHYIF_USELESS = 4
};
/**
* enum caif_direction - CAIF Packet Direction.
* Indicate if a packet is to be sent out or to be received in.
* @CAIF_DIR_IN: Incoming packet received.
* @CAIF_DIR_OUT: Outgoing packet to be transmitted.
*/
enum caif_direction {
CAIF_DIR_IN = 0,
CAIF_DIR_OUT = 1
};
/**
* struct cflayer - CAIF Stack layer.
* Defines the framework for the CAIF Core Stack.
* @up: Pointer up to the layer above.
* @dn: Pointer down to the layer below.
* @node: List node used when layer participate in a list.
* @receive: Packet receive function.
* @transmit: Packet transmit funciton.
* @ctrlcmd: Used for control signalling upwards in the stack.
* @modemcmd: Used for control signaling downwards in the stack.
* @id: The identity 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's private data.
*
* - In order to send data upwards do
* layer->up->receive(layer->up, packet);
*
* - In order to send data downwards do
* layer->dn->transmit(layer->dn, info, packet);
*/
struct cflayer {
struct cflayer *up;
struct cflayer *dn;
struct list_head node;
/*
* receive() - Receive Function (non-blocking).
* Contract: Each layer must implement a receive function passing the
* CAIF packets upwards in the stack.
* Packet handling rules:
* - The CAIF packet (cfpkt) ownership is passed to the
* called receive function. This means that the the
* packet cannot be accessed after passing it to the
* above layer using up->receive().
*
* - If parsing of the packet fails, the packet must be
* destroyed and negative error code returned
* from the function.
* EXCEPTION: If the framing layer (cffrml) returns
* -EILSEQ, the packet is not freed.
*
* - If parsing succeeds (and above layers return OK) then
* the function must return a value >= 0.
*
* Returns result < 0 indicates an error, 0 or positive value
* indicates success.
*
* @layr: Pointer to the current layer the receive function is
* implemented for (this pointer).
* @cfpkt: Pointer to CaifPacket to be handled.
*/
int (*receive)(struct cflayer *layr, struct cfpkt *cfpkt);
/*
* transmit() - Transmit Function (non-blocking).
* 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().
*
* - Upon error the packet ownership is still passed on,
* so the packet shall be freed where error is detected.
* Callers of the transmit function shall not free packets,
* but errors shall be returned.
*
* - Return value less than zero means error, zero or
* greater than zero means OK.
*
* Returns result < 0 indicates an error, 0 or positive value
* indicates success.
*
* @layr: Pointer to the current layer the receive function
* isimplemented for (this pointer).
* @cfpkt: Pointer to CaifPacket to be handled.
*/
int (*transmit) (struct cflayer *layr, struct cfpkt *cfpkt);
/*
* cttrlcmd() - Control Function upwards in CAIF Stack (non-blocking).
* Used for signaling responses (CAIF_CTRLCMD_*_RSP)
* and asynchronous events from the modem (CAIF_CTRLCMD_*_IND)
*
* @layr: Pointer to the current layer the receive function
* is implemented for (this pointer).
* @ctrl: Control Command.
*/
void (*ctrlcmd) (struct cflayer *layr, enum caif_ctrlcmd ctrl,
int phyid);
/*
* modemctrl() - Control Function used for controlling the modem.
* Used to signal down-wards in the CAIF stack.
* Returns 0 on success, < 0 upon failure.
*
* @layr: Pointer to the current layer the receive function
* is implemented for (this pointer).
* @ctrl: Control Command.
*/
int (*modemcmd) (struct cflayer *layr, enum caif_modemcmd ctrl);
unsigned int id;
char name[CAIF_LAYER_NAME_SZ];
};
/**
* layer_set_up() - Set the up pointer for a specified layer.
* @layr: Layer where up pointer shall be set.
* @above: Layer above.
*/
#define layer_set_up(layr, above) ((layr)->up = (struct cflayer *)(above))
/**
* layer_set_dn() - Set the down pointer for a specified layer.
* @layr: Layer where down pointer shall be set.
* @below: Layer below.
*/
#define layer_set_dn(layr, below) ((layr)->dn = (struct cflayer *)(below))
/**
* struct dev_info - Physical Device info information about physical layer.
* @dev: Pointer to native physical device.
* @id: Physical ID of the physical connection used by the
* logical CAIF connection. Used by service layers to
* identify their physical id to Caif MUX (CFMUXL)so
* that the MUX can add the correct physical ID to the
* packet.
*/
struct dev_info {
void *dev;
unsigned int id;
};
/**
* struct caif_payload_info - Payload information embedded in packet (sk_buff).
*
* @dev_info: Information about the receiving device.
*
* @hdr_len: Header length, used to align pay load on 32bit boundary.
*
* @channel_id: Channel ID of the logical CAIF connection.
* Used by mux to insert channel id into the caif packet.
*/
struct caif_payload_info {
struct dev_info *dev_info;
unsigned short hdr_len;
unsigned short channel_id;
};
#endif /* CAIF_LAYER_H_ */
+155
View File
@@ -0,0 +1,155 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Daniel Martensson / Daniel.Martensson@stericsson.com
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_SPI_H_
#define CAIF_SPI_H_
#include <net/caif/caif_device.h>
#define SPI_CMD_WR 0x00
#define SPI_CMD_RD 0x01
#define SPI_CMD_EOT 0x02
#define SPI_CMD_IND 0x04
#define SPI_DMA_BUF_LEN 8192
#define WL_SZ 2 /* 16 bits. */
#define SPI_CMD_SZ 4 /* 32 bits. */
#define SPI_IND_SZ 4 /* 32 bits. */
#define SPI_XFER 0
#define SPI_SS_ON 1
#define SPI_SS_OFF 2
#define SPI_TERMINATE 3
/* Minimum time between different levels is 50 microseconds. */
#define MIN_TRANSITION_TIME_USEC 50
/* Defines for calculating duration of SPI transfers for a particular
* number of bytes.
*/
#define SPI_MASTER_CLK_MHZ 13
#define SPI_XFER_TIME_USEC(bytes, clk) (((bytes) * 8) / clk)
/* Normally this should be aligned on the modem in order to benefit from full
* duplex transfers. However a size of 8188 provokes errors when running with
* the modem. These errors occur when packet sizes approaches 4 kB of data.
*/
#define CAIF_MAX_SPI_FRAME 4092
/* Maximum number of uplink CAIF frames that can reside in the same SPI frame.
* This number should correspond with the modem setting. The application side
* CAIF accepts any number of embedded downlink CAIF frames.
*/
#define CAIF_MAX_SPI_PKTS 9
/* Decides if SPI buffers should be prefilled with 0xFF pattern for easier
* debugging. Both TX and RX buffers will be filled before the transfer.
*/
#define CFSPI_DBG_PREFILL 0
/* Structure describing a SPI transfer. */
struct cfspi_xfer {
u16 tx_dma_len;
u16 rx_dma_len;
void *va_tx[2];
dma_addr_t pa_tx[2];
void *va_rx;
dma_addr_t pa_rx;
};
/* Structure implemented by the SPI interface. */
struct cfspi_ifc {
void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
void (*xfer_done_cb) (struct cfspi_ifc *ifc);
void *priv;
};
/* Structure implemented by SPI clients. */
struct cfspi_dev {
int (*init_xfer) (struct cfspi_xfer *xfer, struct cfspi_dev *dev);
void (*sig_xfer) (bool xfer, struct cfspi_dev *dev);
struct cfspi_ifc *ifc;
char *name;
u32 clk_mhz;
void *priv;
};
/* Enumeration describing the CAIF SPI state. */
enum cfspi_state {
CFSPI_STATE_WAITING = 0,
CFSPI_STATE_AWAKE,
CFSPI_STATE_FETCH_PKT,
CFSPI_STATE_GET_NEXT,
CFSPI_STATE_INIT_XFER,
CFSPI_STATE_WAIT_ACTIVE,
CFSPI_STATE_SIG_ACTIVE,
CFSPI_STATE_WAIT_XFER_DONE,
CFSPI_STATE_XFER_DONE,
CFSPI_STATE_WAIT_INACTIVE,
CFSPI_STATE_SIG_INACTIVE,
CFSPI_STATE_DELIVER_PKT,
CFSPI_STATE_MAX,
};
/* Structure implemented by SPI physical interfaces. */
struct cfspi {
struct caif_dev_common cfdev;
struct net_device *ndev;
struct platform_device *pdev;
struct sk_buff_head qhead;
struct sk_buff_head chead;
u16 cmd;
u16 tx_cpck_len;
u16 tx_npck_len;
u16 rx_cpck_len;
u16 rx_npck_len;
struct cfspi_ifc ifc;
struct cfspi_xfer xfer;
struct cfspi_dev *dev;
unsigned long state;
struct work_struct work;
struct workqueue_struct *wq;
struct list_head list;
int flow_off_sent;
u32 qd_low_mark;
u32 qd_high_mark;
struct completion comp;
wait_queue_head_t wait;
spinlock_t lock;
bool flow_stop;
bool slave;
bool slave_talked;
#ifdef CONFIG_DEBUG_FS
enum cfspi_state dbg_state;
u16 pcmd;
u16 tx_ppck_len;
u16 rx_ppck_len;
struct dentry *dbgfs_dir;
struct dentry *dbgfs_state;
struct dentry *dbgfs_frame;
#endif /* CONFIG_DEBUG_FS */
};
extern int spi_frm_align;
extern int spi_up_head_align;
extern int spi_up_tail_align;
extern int spi_down_head_align;
extern int spi_down_tail_align;
extern struct platform_driver cfspi_spi_driver;
void cfspi_dbg_state(struct cfspi *cfspi, int state);
int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
int cfspi_xmitlen(struct cfspi *cfspi);
int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
int cfspi_spi_remove(struct platform_device *pdev);
int cfspi_spi_probe(struct platform_device *pdev);
int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
int cfspi_xmitlen(struct cfspi *cfspi);
int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
void cfspi_xfer(struct work_struct *work);
#endif /* CAIF_SPI_H_ */
+90
View File
@@ -0,0 +1,90 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFCNFG_H_
#define CFCNFG_H_
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <net/caif/caif_layer.h>
#include <net/caif/cfctrl.h>
struct cfcnfg;
/**
* 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() - Get the CAIF configuration object given network.
* @net: Network for the CAIF configuration object.
*/
struct cfcnfg *get_cfcnfg(struct net *net);
/**
* 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().
* @dev: Pointer to link layer device
* @phy_layer: Specify the physical layer. The transmit function
* MUST be set in the structure.
* @pref: The phy (link layer) preference.
* @link_support: Protocol implementation for link layer specific protocol.
* @fcs: Specify if checksum is used in CAIF Framing Layer.
* @head_room: Head space needed by link specific protocol.
*/
void
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
struct net_device *dev, struct cflayer *phy_layer,
enum cfcnfg_phy_preference pref,
struct cflayer *link_support,
bool fcs, int head_room);
/**
* cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack.
*
* @cnfg: Pointer to a CAIF configuration object, created by
* cfcnfg_create().
* @phy_layer: Adaptation layer to be removed.
*/
int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer);
/**
* cfcnfg_set_phy_state() - Set the state of the physical interface device.
* @cnfg: Configuration object
* @phy_layer: Physical Layer representation
* @up: State of device
*/
int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer,
bool up);
#endif /* CFCNFG_H_ */
+130
View File
@@ -0,0 +1,130 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFCTRL_H_
#define CFCTRL_H_
#include <net/caif/caif_layer.h>
#include <net/caif/cfsrvl.h>
/* CAIF Control packet commands */
enum cfctrl_cmd {
CFCTRL_CMD_LINK_SETUP = 0,
CFCTRL_CMD_LINK_DESTROY = 1,
CFCTRL_CMD_LINK_ERR = 2,
CFCTRL_CMD_ENUM = 3,
CFCTRL_CMD_SLEEP = 4,
CFCTRL_CMD_WAKE = 5,
CFCTRL_CMD_LINK_RECONF = 6,
CFCTRL_CMD_START_REASON = 7,
CFCTRL_CMD_RADIO_SET = 8,
CFCTRL_CMD_MODEM_SET = 9,
CFCTRL_CMD_MASK = 0xf
};
/* Channel types */
enum cfctrl_srv {
CFCTRL_SRV_DECM = 0,
CFCTRL_SRV_VEI = 1,
CFCTRL_SRV_VIDEO = 2,
CFCTRL_SRV_DBG = 3,
CFCTRL_SRV_DATAGRAM = 4,
CFCTRL_SRV_RFM = 5,
CFCTRL_SRV_UTIL = 6,
CFCTRL_SRV_MASK = 0xf
};
#define CFCTRL_RSP_BIT 0x20
#define CFCTRL_ERR_BIT 0x10
struct cfctrl_rsp {
void (*linksetup_rsp)(struct cflayer *layer, u8 linkid,
enum cfctrl_srv serv, u8 phyid,
struct cflayer *adapt_layer);
void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid);
void (*linkerror_ind)(void);
void (*enum_rsp)(void);
void (*sleep_rsp)(void);
void (*wake_rsp)(void);
void (*restart_rsp)(void);
void (*radioset_rsp)(void);
void (*reject_rsp)(struct cflayer *layer, u8 linkid,
struct cflayer *client_layer);
};
/* Link Setup Parameters for CAIF-Links. */
struct cfctrl_link_param {
enum cfctrl_srv linktype;/* (T3,T0) Type of Channel */
u8 priority; /* (P4,P0) Priority of the channel */
u8 phyid; /* (U2-U0) Physical interface to connect */
u8 endpoint; /* (E1,E0) Endpoint for data channels */
u8 chtype; /* (H1,H0) Channel-Type, applies to
* VEI, DEBUG */
union {
struct {
u8 connid; /* (D7,D0) Video LinkId */
} video;
struct {
u32 connid; /* (N31,Ngit0) Connection ID used
* for Datagram */
} datagram;
struct {
u32 connid; /* Connection ID used for RFM */
char volume[20]; /* Volume to mount for RFM */
} rfm; /* Configuration for RFM */
struct {
u16 fifosize_kb; /* Psock FIFO size in KB */
u16 fifosize_bufs; /* Psock # signal buffers */
char name[16]; /* Name of the PSOCK service */
u8 params[255]; /* Link setup Parameters> */
u16 paramlen; /* Length of Link Setup
* Parameters */
} utility; /* Configuration for Utility Links (Psock) */
} u;
};
/* This structure is used internally in CFCTRL */
struct cfctrl_request_info {
int sequence_no;
enum cfctrl_cmd cmd;
u8 channel_id;
struct cfctrl_link_param param;
struct cflayer *client_layer;
struct list_head list;
};
struct cfctrl {
struct cfsrvl serv;
struct cfctrl_rsp res;
atomic_t req_seq_no;
atomic_t rsp_seq_no;
struct list_head list;
/* Protects from simultaneous access to first_req list */
spinlock_t info_list_lock;
#ifndef CAIF_NO_LOOP
u8 loop_linkid;
int loop_linkused[256];
/* Protects simultaneous access to loop_linkid and loop_linkused */
spinlock_t loop_linkid_lock;
#endif
};
void cfctrl_enum_req(struct cflayer *cfctrl, u8 physlinkid);
int cfctrl_linkup_request(struct cflayer *cfctrl,
struct cfctrl_link_param *param,
struct cflayer *user_layer);
int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid,
struct cflayer *client);
struct cflayer *cfctrl_create(void);
struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer);
int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer);
void cfctrl_remove(struct cflayer *layr);
#endif /* CFCTRL_H_ */
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFFRML_H_
#define CFFRML_H_
#include <net/caif/caif_layer.h>
#include <linux/netdevice.h>
struct cffrml;
struct cflayer *cffrml_create(u16 phyid, bool use_fcs);
void cffrml_free(struct cflayer *layr);
void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up);
void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn);
void cffrml_put(struct cflayer *layr);
void cffrml_hold(struct cflayer *layr);
int cffrml_refcnt_read(struct cflayer *layr);
#endif /* CFFRML_H_ */
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFMUXL_H_
#define CFMUXL_H_
#include <net/caif/caif_layer.h>
struct cfsrvl;
struct cffrml;
struct cflayer *cfmuxl_create(void);
int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid);
struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid);
int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *up, u8 phyid);
struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 linkid);
#endif /* CFMUXL_H_ */
+232
View File
@@ -0,0 +1,232 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* 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);
/*
* 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);
static inline u8 cfpkt_extr_head_u8(struct cfpkt *pkt)
{
u8 tmp;
cfpkt_extr_head(pkt, &tmp, 1);
return tmp;
}
static inline u16 cfpkt_extr_head_u16(struct cfpkt *pkt)
{
__le16 tmp;
cfpkt_extr_head(pkt, &tmp, 2);
return le16_to_cpu(tmp);
}
static inline u32 cfpkt_extr_head_u32(struct cfpkt *pkt)
{
__le32 tmp;
cfpkt_extr_head(pkt, &tmp, 4);
return le32_to_cpu(tmp);
}
/*
* 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.
*/
int cfpkt_iterate(struct cfpkt *pkt,
u16 (*iter_func)(u16 chks, void *buf, u16 len),
u16 data);
/* 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);
/*
* Returns packet information for a packet.
* pkt Packet to get info from;
* @return Packet information
*/
struct caif_payload_info *cfpkt_info(struct cfpkt *pkt);
/** cfpkt_set_prio - set priority for a CAIF packet.
*
* @pkt: The CAIF packet to be adjusted.
* @prio: one of TC_PRIO_ constants.
*/
void cfpkt_set_prio(struct cfpkt *pkt, int prio);
#endif /* CFPKT_H_ */
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFSERL_H_
#define CFSERL_H_
#include <net/caif/caif_layer.h>
struct cflayer *cfserl_create(int instance, bool use_stx);
#endif
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFSRVL_H_
#define CFSRVL_H_
#include <linux/list.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/kref.h>
#include <linux/rculist.h>
struct cfsrvl {
struct cflayer layer;
bool open;
bool phy_flow_on;
bool modem_flow_on;
bool supports_flowctrl;
void (*release)(struct cflayer *layer);
struct dev_info dev_info;
void (*hold)(struct cflayer *lyr);
void (*put)(struct cflayer *lyr);
struct rcu_head rcu;
};
struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info,
int mtu_size);
struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info);
void cfsrvl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
int phyid);
bool cfsrvl_phyid_match(struct cflayer *layer, int phyid);
void cfsrvl_init(struct cfsrvl *service,
u8 channel_id,
struct dev_info *dev_info,
bool supports_flowctrl);
bool cfsrvl_ready(struct cfsrvl *service, int *err);
u8 cfsrvl_getphyid(struct cflayer *layer);
static inline void cfsrvl_get(struct cflayer *layr)
{
struct cfsrvl *s = container_of(layr, struct cfsrvl, layer);
if (layr == NULL || layr->up == NULL || s->hold == NULL)
return;
s->hold(layr->up);
}
static inline void cfsrvl_put(struct cflayer *layr)
{
struct cfsrvl *s = container_of(layr, struct cfsrvl, layer);
if (layr == NULL || layr->up == NULL || s->hold == NULL)
return;
s->put(layr->up);
}
#endif /* CFSRVL_H_ */
+91
View File
@@ -0,0 +1,91 @@
/*
* CALIPSO - Common Architecture Label IPv6 Security Option
*
* This is an implementation of the CALIPSO protocol as specified in
* RFC 5570.
*
* Authors: Paul Moore <paul@paul-moore.com>
* Huw Davies <huw@codeweavers.com>
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* (c) Copyright Huw Davies <huw@codeweavers.com>, 2015
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _CALIPSO_H
#define _CALIPSO_H
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <net/netlabel.h>
#include <net/request_sock.h>
#include <linux/refcount.h>
#include <asm/unaligned.h>
/* known doi values */
#define CALIPSO_DOI_UNKNOWN 0x00000000
/* doi mapping types */
#define CALIPSO_MAP_UNKNOWN 0
#define CALIPSO_MAP_PASS 2
/*
* CALIPSO DOI definitions
*/
/* DOI definition struct */
struct calipso_doi {
u32 doi;
u32 type;
refcount_t refcount;
struct list_head list;
struct rcu_head rcu;
};
/*
* Sysctl Variables
*/
extern int calipso_cache_enabled;
extern int calipso_cache_bucketsize;
#ifdef CONFIG_NETLABEL
int __init calipso_init(void);
void calipso_exit(void);
bool calipso_validate(const struct sk_buff *skb, const unsigned char *option);
#else
static inline int __init calipso_init(void)
{
return 0;
}
static inline void calipso_exit(void)
{
}
static inline bool calipso_validate(const struct sk_buff *skb,
const unsigned char *option)
{
return true;
}
#endif /* CONFIG_NETLABEL */
#endif /* _CALIPSO_H */
+55
View File
@@ -0,0 +1,55 @@
#ifndef __NET_CFG80211_WEXT_H
#define __NET_CFG80211_WEXT_H
/*
* 802.11 device and configuration interface -- wext handlers
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
/*
* Temporary wext handlers & helper functions
*
* These are used only by drivers that aren't yet fully
* converted to cfg80211.
*/
int cfg80211_wext_giwname(struct net_device *dev,
struct iw_request_info *info,
char *name, char *extra);
int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
u32 *mode, char *extra);
int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
u32 *mode, char *extra);
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwscan(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
int cfg80211_wext_giwrange(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
int cfg80211_wext_siwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra);
int cfg80211_wext_giwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra);
int cfg80211_wext_siwfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frag, char *extra);
int cfg80211_wext_giwfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frag, char *extra);
int cfg80211_wext_giwretry(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *retry, char *extra);
#endif /* __NET_CFG80211_WEXT_H */
File diff suppressed because it is too large. Load diff
+416
View File
@@ -0,0 +1,416 @@
/*
* Copyright (C) 2007, 2008, 2009 Siemens AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Written by:
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
*/
#ifndef __NET_CFG802154_H
#define __NET_CFG802154_H
#include <linux/ieee802154.h>
#include <linux/netdevice.h>
#include <linux/mutex.h>
#include <linux/bug.h>
#include <net/nl802154.h>
struct wpan_phy;
struct wpan_phy_cca;
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
struct ieee802154_llsec_device_key;
struct ieee802154_llsec_seclevel;
struct ieee802154_llsec_params;
struct ieee802154_llsec_device;
struct ieee802154_llsec_table;
struct ieee802154_llsec_key_id;
struct ieee802154_llsec_key;
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
struct cfg802154_ops {
struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
const char *name,
unsigned char name_assign_type,
int type);
void (*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
struct net_device *dev);
int (*suspend)(struct wpan_phy *wpan_phy);
int (*resume)(struct wpan_phy *wpan_phy);
int (*add_virtual_intf)(struct wpan_phy *wpan_phy,
const char *name,
unsigned char name_assign_type,
enum nl802154_iftype type,
__le64 extended_addr);
int (*del_virtual_intf)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev);
int (*set_channel)(struct wpan_phy *wpan_phy, u8 page, u8 channel);
int (*set_cca_mode)(struct wpan_phy *wpan_phy,
const struct wpan_phy_cca *cca);
int (*set_cca_ed_level)(struct wpan_phy *wpan_phy, s32 ed_level);
int (*set_tx_power)(struct wpan_phy *wpan_phy, s32 power);
int (*set_pan_id)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, __le16 pan_id);
int (*set_short_addr)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, __le16 short_addr);
int (*set_backoff_exponent)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, u8 min_be,
u8 max_be);
int (*set_max_csma_backoffs)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
u8 max_csma_backoffs);
int (*set_max_frame_retries)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
s8 max_frame_retries);
int (*set_lbt_mode)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, bool mode);
int (*set_ackreq_default)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, bool ackreq);
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
void (*get_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
struct ieee802154_llsec_table **table);
void (*lock_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev);
void (*unlock_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev);
/* TODO remove locking/get table callbacks, this is part of the
* nl802154 interface and should be accessible from ieee802154 layer.
*/
int (*get_llsec_params)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
struct ieee802154_llsec_params *params);
int (*set_llsec_params)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_params *params,
int changed);
int (*add_llsec_key)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_key_id *id,
const struct ieee802154_llsec_key *key);
int (*del_llsec_key)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_key_id *id);
int (*add_seclevel)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_seclevel *sl);
int (*del_seclevel)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_seclevel *sl);
int (*add_device)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
const struct ieee802154_llsec_device *dev);
int (*del_device)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev, __le64 extended_addr);
int (*add_devkey)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
__le64 extended_addr,
const struct ieee802154_llsec_device_key *key);
int (*del_devkey)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
__le64 extended_addr,
const struct ieee802154_llsec_device_key *key);
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
};
static inline bool
wpan_phy_supported_bool(bool b, enum nl802154_supported_bool_states st)
{
switch (st) {
case NL802154_SUPPORTED_BOOL_TRUE:
return b;
case NL802154_SUPPORTED_BOOL_FALSE:
return !b;
case NL802154_SUPPORTED_BOOL_BOTH:
return true;
default:
WARN_ON(1);
}
return false;
}
struct wpan_phy_supported {
u32 channels[IEEE802154_MAX_PAGE + 1],
cca_modes, cca_opts, iftypes;
enum nl802154_supported_bool_states lbt;
u8 min_minbe, max_minbe, min_maxbe, max_maxbe,
min_csma_backoffs, max_csma_backoffs;
s8 min_frame_retries, max_frame_retries;
size_t tx_powers_size, cca_ed_levels_size;
const s32 *tx_powers, *cca_ed_levels;
};
struct wpan_phy_cca {
enum nl802154_cca_modes mode;
enum nl802154_cca_opts opt;
};
static inline bool
wpan_phy_cca_cmp(const struct wpan_phy_cca *a, const struct wpan_phy_cca *b)
{
if (a->mode != b->mode)
return false;
if (a->mode == NL802154_CCA_ENERGY_CARRIER)
return a->opt == b->opt;
return true;
}
/**
* @WPAN_PHY_FLAG_TRANSMIT_POWER: Indicates that transceiver will support
* transmit power setting.
* @WPAN_PHY_FLAG_CCA_ED_LEVEL: Indicates that transceiver will support cca ed
* level setting.
* @WPAN_PHY_FLAG_CCA_MODE: Indicates that transceiver will support cca mode
* setting.
*/
enum wpan_phy_flags {
WPAN_PHY_FLAG_TXPOWER = BIT(1),
WPAN_PHY_FLAG_CCA_ED_LEVEL = BIT(2),
WPAN_PHY_FLAG_CCA_MODE = BIT(3),
};
struct wpan_phy {
/* If multiple wpan_phys are registered and you're handed e.g.
* a regular netdev with assigned ieee802154_ptr, you won't
* know whether it points to a wpan_phy your driver has registered
* or not. Assign this to something global to your driver to
* help determine whether you own this wpan_phy or not.
*/
const void *privid;
u32 flags;
/*
* This is a PIB according to 802.15.4-2011.
* We do not provide timing-related variables, as they
* aren't used outside of driver
*/
u8 current_channel;
u8 current_page;
struct wpan_phy_supported supported;
/* current transmit_power in mBm */
s32 transmit_power;
struct wpan_phy_cca cca;
__le64 perm_extended_addr;
/* current cca ed threshold in mBm */
s32 cca_ed_level;
/* PHY depended MAC PIB values */
/* 802.15.4 acronym: Tdsym in usec */
u8 symbol_duration;
/* lifs and sifs periods timing */
u16 lifs_period;
u16 sifs_period;
struct device dev;
/* the network namespace this phy lives in currently */
possible_net_t _net;
char priv[0] __aligned(NETDEV_ALIGN);
};
static inline struct net *wpan_phy_net(struct wpan_phy *wpan_phy)
{
return read_pnet(&wpan_phy->_net);
}
static inline void wpan_phy_net_set(struct wpan_phy *wpan_phy, struct net *net)
{
write_pnet(&wpan_phy->_net, net);
}
struct ieee802154_addr {
u8 mode;
__le16 pan_id;
union {
__le16 short_addr;
__le64 extended_addr;
};
};
struct ieee802154_llsec_key_id {
u8 mode;
u8 id;
union {
struct ieee802154_addr device_addr;
__le32 short_source;
__le64 extended_source;
};
};
#define IEEE802154_LLSEC_KEY_SIZE 16
struct ieee802154_llsec_key {
u8 frame_types;
u32 cmd_frame_ids;
/* TODO replace with NL802154_KEY_SIZE */
u8 key[IEEE802154_LLSEC_KEY_SIZE];
};
struct ieee802154_llsec_key_entry {
struct list_head list;
struct ieee802154_llsec_key_id id;
struct ieee802154_llsec_key *key;
};
struct ieee802154_llsec_params {
bool enabled;
__be32 frame_counter;
u8 out_level;
struct ieee802154_llsec_key_id out_key;
__le64 default_key_source;
__le16 pan_id;
__le64 hwaddr;
__le64 coord_hwaddr;
__le16 coord_shortaddr;
};
struct ieee802154_llsec_table {
struct list_head keys;
struct list_head devices;
struct list_head security_levels;
};
struct ieee802154_llsec_seclevel {
struct list_head list;
u8 frame_type;
u8 cmd_frame_id;
bool device_override;
u32 sec_levels;
};
struct ieee802154_llsec_device {
struct list_head list;
__le16 pan_id;
__le16 short_addr;
__le64 hwaddr;
u32 frame_counter;
bool seclevel_exempt;
u8 key_mode;
struct list_head keys;
};
struct ieee802154_llsec_device_key {
struct list_head list;
struct ieee802154_llsec_key_id key_id;
u32 frame_counter;
};
struct wpan_dev_header_ops {
/* TODO create callback currently assumes ieee802154_mac_cb inside
* skb->cb. This should be changed to give these information as
* parameter.
*/
int (*create)(struct sk_buff *skb, struct net_device *dev,
const struct ieee802154_addr *daddr,
const struct ieee802154_addr *saddr,
unsigned int len);
};
struct wpan_dev {
struct wpan_phy *wpan_phy;
int iftype;
/* the remainder of this struct should be private to cfg802154 */
struct list_head list;
struct net_device *netdev;
const struct wpan_dev_header_ops *header_ops;
/* lowpan interface, set when the wpan_dev belongs to one lowpan_dev */
struct net_device *lowpan_dev;
u32 identifier;
/* MAC PIB */
__le16 pan_id;
__le16 short_addr;
__le64 extended_addr;
/* MAC BSN field */
atomic_t bsn;
/* MAC DSN field */
atomic_t dsn;
u8 min_be;
u8 max_be;
u8 csma_retries;
s8 frame_retries;
bool lbt;
bool promiscuous_mode;
/* fallback for acknowledgment bit setting */
bool ackreq;
};
#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
static inline int
wpan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
const struct ieee802154_addr *daddr,
const struct ieee802154_addr *saddr,
unsigned int len)
{
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
return wpan_dev->header_ops->create(skb, dev, daddr, saddr, len);
}
struct wpan_phy *
wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size);
static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
{
phy->dev.parent = dev;
}
int wpan_phy_register(struct wpan_phy *phy);
void wpan_phy_unregister(struct wpan_phy *phy);
void wpan_phy_free(struct wpan_phy *phy);
/* Same semantics as for class_for_each_device */
int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), void *data);
static inline void *wpan_phy_priv(struct wpan_phy *phy)
{
BUG_ON(!phy);
return &phy->priv;
}
struct wpan_phy *wpan_phy_find(const char *str);
static inline void wpan_phy_put(struct wpan_phy *phy)
{
put_device(&phy->dev);
}
static inline const char *wpan_phy_name(struct wpan_phy *phy)
{
return dev_name(&phy->dev);
}
#endif /* __NET_CFG802154_H */
+185
View File
@@ -0,0 +1,185 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Checksumming functions for IP, TCP, UDP and so on
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Borrows very liberally from tcp.c and ip.c, see those
* files for more names.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _CHECKSUM_H
#define _CHECKSUM_H
#include <linux/errno.h>
#include <asm/types.h>
#include <asm/byteorder.h>
#include <linux/uaccess.h>
#include <asm/checksum.h>
#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
static inline
__wsum csum_and_copy_from_user (const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
{
if (access_ok(VERIFY_READ, src, len))
return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
if (len)
*err_ptr = -EFAULT;
return sum;
}
#endif
#ifndef HAVE_CSUM_COPY_USER
static __inline__ __wsum csum_and_copy_to_user
(const void *src, void __user *dst, int len, __wsum sum, int *err_ptr)
{
sum = csum_partial(src, len, sum);
if (access_ok(VERIFY_WRITE, dst, len)) {
if (copy_to_user(dst, src, len) == 0)
return sum;
}
if (len)
*err_ptr = -EFAULT;
return (__force __wsum)-1; /* invalid checksum */
}
#endif
#ifndef HAVE_ARCH_CSUM_ADD
static inline __wsum csum_add(__wsum csum, __wsum addend)
{
u32 res = (__force u32)csum;
res += (__force u32)addend;
return (__force __wsum)(res + (res < (__force u32)addend));
}
#endif
static inline __wsum csum_sub(__wsum csum, __wsum addend)
{
return csum_add(csum, ~addend);
}
static inline __sum16 csum16_add(__sum16 csum, __be16 addend)
{
u16 res = (__force u16)csum;
res += (__force u16)addend;
return (__force __sum16)(res + (res < (__force u16)addend));
}
static inline __sum16 csum16_sub(__sum16 csum, __be16 addend)
{
return csum16_add(csum, ~addend);
}
static inline __wsum
csum_block_add(__wsum csum, __wsum csum2, int offset)
{
u32 sum = (__force u32)csum2;
/* rotate sum to align it with a 16b boundary */
if (offset & 1)
sum = ror32(sum, 8);
return csum_add(csum, (__force __wsum)sum);
}
static inline __wsum
csum_block_add_ext(__wsum csum, __wsum csum2, int offset, int len)
{
return csum_block_add(csum, csum2, offset);
}
static inline __wsum
csum_block_sub(__wsum csum, __wsum csum2, int offset)
{
return csum_block_add(csum, ~csum2, offset);
}
static inline __wsum csum_unfold(__sum16 n)
{
return (__force __wsum)n;
}
static inline __wsum csum_partial_ext(const void *buff, int len, __wsum sum)
{
return csum_partial(buff, len, sum);
}
#define CSUM_MANGLED_0 ((__force __sum16)0xffff)
static inline void csum_replace_by_diff(__sum16 *sum, __wsum diff)
{
*sum = csum_fold(csum_add(diff, ~csum_unfold(*sum)));
}
static inline void csum_replace4(__sum16 *sum, __be32 from, __be32 to)
{
__wsum tmp = csum_sub(~csum_unfold(*sum), (__force __wsum)from);
*sum = csum_fold(csum_add(tmp, (__force __wsum)to));
}
/* Implements RFC 1624 (Incremental Internet Checksum)
* 3. Discussion states :
* HC' = ~(~HC + ~m + m')
* m : old value of a 16bit field
* m' : new value of a 16bit field
*/
static inline void csum_replace2(__sum16 *sum, __be16 old, __be16 new)
{
*sum = ~csum16_add(csum16_sub(~(*sum), old), new);
}
struct sk_buff;
void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
__be32 from, __be32 to, bool pseudohdr);
void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
const __be32 *from, const __be32 *to,
bool pseudohdr);
void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
__wsum diff, bool pseudohdr);
static inline void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
__be16 from, __be16 to,
bool pseudohdr)
{
inet_proto_csum_replace4(sum, skb, (__force __be32)from,
(__force __be32)to, pseudohdr);
}
static inline __wsum remcsum_adjust(void *ptr, __wsum csum,
int start, int offset)
{
__sum16 *psum = (__sum16 *)(ptr + offset);
__wsum delta;
/* Subtract out checksum up to start */
csum = csum_sub(csum, csum_partial(ptr, start, 0));
/* Set derived checksum in packet */
delta = csum_sub((__force __wsum)csum_fold(csum),
(__force __wsum)*psum);
*psum = csum_fold(csum);
return delta;
}
static inline void remcsum_unadjust(__sum16 *psum, __wsum delta)
{
*psum = csum_fold(csum_sub(delta, (__force __wsum)*psum));
}
#endif
+332
View File
@@ -0,0 +1,332 @@
/*
* CIPSO - Commercial IP Security Option
*
* This is an implementation of the CIPSO 2.2 protocol as specified in
* draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
* FIPS-188, copies of both documents can be found in the Documentation
* directory. While CIPSO never became a full IETF RFC standard many vendors
* have chosen to adopt the protocol and over the years it has become a
* de-facto standard for labeled networking.
*
* Author: Paul Moore <paul@paul-moore.com>
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _CIPSO_IPV4_H
#define _CIPSO_IPV4_H
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <net/netlabel.h>
#include <net/request_sock.h>
#include <linux/atomic.h>
#include <linux/refcount.h>
#include <asm/unaligned.h>
/* known doi values */
#define CIPSO_V4_DOI_UNKNOWN 0x00000000
/* standard tag types */
#define CIPSO_V4_TAG_INVALID 0
#define CIPSO_V4_TAG_RBITMAP 1
#define CIPSO_V4_TAG_ENUM 2
#define CIPSO_V4_TAG_RANGE 5
#define CIPSO_V4_TAG_PBITMAP 6
#define CIPSO_V4_TAG_FREEFORM 7
/* non-standard tag types (tags > 127) */
#define CIPSO_V4_TAG_LOCAL 128
/* doi mapping types */
#define CIPSO_V4_MAP_UNKNOWN 0
#define CIPSO_V4_MAP_TRANS 1
#define CIPSO_V4_MAP_PASS 2
#define CIPSO_V4_MAP_LOCAL 3
/* limits */
#define CIPSO_V4_MAX_REM_LVLS 255
#define CIPSO_V4_INV_LVL 0x80000000
#define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1)
#define CIPSO_V4_MAX_REM_CATS 65534
#define CIPSO_V4_INV_CAT 0x80000000
#define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1)
/*
* CIPSO DOI definitions
*/
/* DOI definition struct */
#define CIPSO_V4_TAG_MAXCNT 5
struct cipso_v4_doi {
u32 doi;
u32 type;
union {
struct cipso_v4_std_map_tbl *std;
} map;
u8 tags[CIPSO_V4_TAG_MAXCNT];
refcount_t refcount;
struct list_head list;
struct rcu_head rcu;
};
/* Standard CIPSO mapping table */
/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the
* bit is set then consider that value as unspecified, meaning the
* mapping for that particular level/category is invalid */
struct cipso_v4_std_map_tbl {
struct {
u32 *cipso;
u32 *local;
u32 cipso_size;
u32 local_size;
} lvl;
struct {
u32 *cipso;
u32 *local;
u32 cipso_size;
u32 local_size;
} cat;
};
/*
* Sysctl Variables
*/
#ifdef CONFIG_NETLABEL
extern int cipso_v4_cache_enabled;
extern int cipso_v4_cache_bucketsize;
extern int cipso_v4_rbm_optfmt;
extern int cipso_v4_rbm_strictvalid;
#endif
/*
* DOI List Functions
*/
#ifdef CONFIG_NETLABEL
int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
struct netlbl_audit *audit_info);
void cipso_v4_doi_free(struct cipso_v4_doi *doi_def);
int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info);
struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def);
int cipso_v4_doi_walk(u32 *skip_cnt,
int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
void *cb_arg);
#else
static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
struct netlbl_audit *audit_info)
{
return -ENOSYS;
}
static inline void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
{
return;
}
static inline int cipso_v4_doi_remove(u32 doi,
struct netlbl_audit *audit_info)
{
return 0;
}
static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
{
return NULL;
}
static inline int cipso_v4_doi_walk(u32 *skip_cnt,
int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
void *cb_arg)
{
return 0;
}
static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def,
const char *domain)
{
return -ENOSYS;
}
static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
const char *domain)
{
return 0;
}
#endif /* CONFIG_NETLABEL */
/*
* Label Mapping Cache Functions
*/
#ifdef CONFIG_NETLABEL
void cipso_v4_cache_invalidate(void);
int cipso_v4_cache_add(const unsigned char *cipso_ptr,
const struct netlbl_lsm_secattr *secattr);
#else
static inline void cipso_v4_cache_invalidate(void)
{
return;
}
static inline int cipso_v4_cache_add(const unsigned char *cipso_ptr,
const struct netlbl_lsm_secattr *secattr)
{
return 0;
}
#endif /* CONFIG_NETLABEL */
/*
* Protocol Handling Functions
*/
#ifdef CONFIG_NETLABEL
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
int cipso_v4_getattr(const unsigned char *cipso,
struct netlbl_lsm_secattr *secattr);
int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
void cipso_v4_sock_delattr(struct sock *sk);
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
int cipso_v4_req_setattr(struct request_sock *req,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
void cipso_v4_req_delattr(struct request_sock *req);
int cipso_v4_skbuff_setattr(struct sk_buff *skb,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
int cipso_v4_skbuff_delattr(struct sk_buff *skb);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr);
unsigned char *cipso_v4_optptr(const struct sk_buff *skb);
int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
#else
static inline void cipso_v4_error(struct sk_buff *skb,
int error,
u32 gateway)
{
return;
}
static inline int cipso_v4_getattr(const unsigned char *cipso,
struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline void cipso_v4_sock_delattr(struct sock *sk)
{
}
static inline int cipso_v4_sock_getattr(struct sock *sk,
struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int cipso_v4_req_setattr(struct request_sock *req,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline void cipso_v4_req_delattr(struct request_sock *req)
{
return;
}
static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int cipso_v4_skbuff_delattr(struct sk_buff *skb)
{
return -ENOSYS;
}
static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
{
return NULL;
}
static inline int cipso_v4_validate(const struct sk_buff *skb,
unsigned char **option)
{
unsigned char *opt = *option;
unsigned char err_offset = 0;
u8 opt_len = opt[1];
u8 opt_iter;
u8 tag_len;
if (opt_len < 8) {
err_offset = 1;
goto out;
}
if (get_unaligned_be32(&opt[2]) == 0) {
err_offset = 2;
goto out;
}
for (opt_iter = 6; opt_iter < opt_len;) {
if (opt_iter + 1 == opt_len) {
err_offset = opt_iter;
goto out;
}
tag_len = opt[opt_iter + 1];
if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
err_offset = opt_iter + 1;
goto out;
}
opt_iter += tag_len;
}
out:
*option = opt + err_offset;
return err_offset;
}
#endif /* CONFIG_NETLABEL */
#endif /* _CIPSO_IPV4_H */
+88
View File
@@ -0,0 +1,88 @@
/*
* cls_cgroup.h Control Group Classifier
*
* Authors: Thomas Graf <tgraf@suug.ch>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
#ifndef _NET_CLS_CGROUP_H
#define _NET_CLS_CGROUP_H
#include <linux/cgroup.h>
#include <linux/hardirq.h>
#include <linux/rcupdate.h>
#include <net/sock.h>
#include <net/inet_sock.h>
#ifdef CONFIG_CGROUP_NET_CLASSID
struct cgroup_cls_state {
struct cgroup_subsys_state css;
u32 classid;
};
struct cgroup_cls_state *task_cls_state(struct task_struct *p);
static inline u32 task_cls_classid(struct task_struct *p)
{
u32 classid;
if (in_interrupt())
return 0;
rcu_read_lock();
classid = container_of(task_css(p, net_cls_cgrp_id),
struct cgroup_cls_state, css)->classid;
rcu_read_unlock();
return classid;
}
static inline void sock_update_classid(struct sock_cgroup_data *skcd)
{
u32 classid;
classid = task_cls_classid(current);
sock_cgroup_set_classid(skcd, classid);
}
static inline u32 task_get_classid(const struct sk_buff *skb)
{
u32 classid = task_cls_state(current)->classid;
/* Due to the nature of the classifier it is required to ignore all
* packets originating from softirq context as accessing `current'
* would lead to false results.
*
* This test assumes that all callers of dev_queue_xmit() explicitly
* disable bh. Knowing this, it is possible to detect softirq based
* calls by looking at the number of nested bh disable calls because
* softirqs always disables bh.
*/
if (in_serving_softirq()) {
struct sock *sk = skb_to_full_sk(skb);
/* If there is an sock_cgroup_classid we'll use that. */
if (!sk || !sk_fullsock(sk))
return 0;
classid = sock_cgroup_classid(&sk->sk_cgrp_data);
}
return classid;
}
#else /* !CONFIG_CGROUP_NET_CLASSID */
static inline void sock_update_classid(struct sock_cgroup_data *skcd)
{
}
static inline u32 task_get_classid(const struct sk_buff *skb)
{
return 0;
}
#endif /* CONFIG_CGROUP_NET_CLASSID */
#endif /* _NET_CLS_CGROUP_H */
+164
View File
@@ -0,0 +1,164 @@
#ifndef __NET_SCHED_CODEL_H
#define __NET_SCHED_CODEL_H
/*
* Codel - The Controlled-Delay Active Queue Management algorithm
*
* Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
* Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
* Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
* Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
#include <linux/types.h>
#include <linux/ktime.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>
#include <net/inet_ecn.h>
/* Controlling Queue Delay (CoDel) algorithm
* =========================================
* Source : Kathleen Nichols and Van Jacobson
* http://queue.acm.org/detail.cfm?id=2209336
*
* Implemented on linux by Dave Taht and Eric Dumazet
*/
/* CoDel uses a 1024 nsec clock, encoded in u32
* This gives a range of 2199 seconds, because of signed compares
*/
typedef u32 codel_time_t;
typedef s32 codel_tdiff_t;
#define CODEL_SHIFT 10
#define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT)
static inline codel_time_t codel_get_time(void)
{
u64 ns = ktime_get_ns();
return ns >> CODEL_SHIFT;
}
/* Dealing with timer wrapping, according to RFC 1982, as desc in wikipedia:
* https://en.wikipedia.org/wiki/Serial_number_arithmetic#General_Solution
* codel_time_after(a,b) returns true if the time a is after time b.
*/
#define codel_time_after(a, b) \
(typecheck(codel_time_t, a) && \
typecheck(codel_time_t, b) && \
((s32)((a) - (b)) > 0))
#define codel_time_before(a, b) codel_time_after(b, a)
#define codel_time_after_eq(a, b) \
(typecheck(codel_time_t, a) && \
typecheck(codel_time_t, b) && \
((s32)((a) - (b)) >= 0))
#define codel_time_before_eq(a, b) codel_time_after_eq(b, a)
static inline u32 codel_time_to_us(codel_time_t val)
{
u64 valns = ((u64)val << CODEL_SHIFT);
do_div(valns, NSEC_PER_USEC);
return (u32)valns;
}
/**
* struct codel_params - contains codel parameters
* @target: target queue size (in time units)
* @ce_threshold: threshold for marking packets with ECN CE
* @interval: width of moving time window
* @mtu: device mtu, or minimal queue backlog in bytes.
* @ecn: is Explicit Congestion Notification enabled
*/
struct codel_params {
codel_time_t target;
codel_time_t ce_threshold;
codel_time_t interval;
u32 mtu;
bool ecn;
};
/**
* struct codel_vars - contains codel variables
* @count: how many drops we've done since the last time we
* entered dropping state
* @lastcount: count at entry to dropping state
* @dropping: set to true if in dropping state
* @rec_inv_sqrt: reciprocal value of sqrt(count) >> 1
* @first_above_time: when we went (or will go) continuously above target
* for interval
* @drop_next: time to drop next packet, or when we dropped last
* @ldelay: sojourn time of last dequeued packet
*/
struct codel_vars {
u32 count;
u32 lastcount;
bool dropping;
u16 rec_inv_sqrt;
codel_time_t first_above_time;
codel_time_t drop_next;
codel_time_t ldelay;
};
#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
/* needed shift to get a Q0.32 number from rec_inv_sqrt */
#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
/**
* struct codel_stats - contains codel shared variables and stats
* @maxpacket: largest packet we've seen so far
* @drop_count: temp count of dropped packets in dequeue()
* @drop_len: bytes of dropped packets in dequeue()
* ecn_mark: number of packets we ECN marked instead of dropping
* ce_mark: number of packets CE marked because sojourn time was above ce_threshold
*/
struct codel_stats {
u32 maxpacket;
u32 drop_count;
u32 drop_len;
u32 ecn_mark;
u32 ce_mark;
};
#define CODEL_DISABLED_THRESHOLD INT_MAX
typedef u32 (*codel_skb_len_t)(const struct sk_buff *skb);
typedef codel_time_t (*codel_skb_time_t)(const struct sk_buff *skb);
typedef void (*codel_skb_drop_t)(struct sk_buff *skb, void *ctx);
typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars,
void *ctx);
#endif
+255
View File
@@ -0,0 +1,255 @@
#ifndef __NET_SCHED_CODEL_IMPL_H
#define __NET_SCHED_CODEL_IMPL_H
/*
* Codel - The Controlled-Delay Active Queue Management algorithm
*
* Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
* Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
* Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
* Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
/* Controlling Queue Delay (CoDel) algorithm
* =========================================
* Source : Kathleen Nichols and Van Jacobson
* http://queue.acm.org/detail.cfm?id=2209336
*
* Implemented on linux by Dave Taht and Eric Dumazet
*/
static void codel_params_init(struct codel_params *params)
{
params->interval = MS2TIME(100);
params->target = MS2TIME(5);
params->ce_threshold = CODEL_DISABLED_THRESHOLD;
params->ecn = false;
}
static void codel_vars_init(struct codel_vars *vars)
{
memset(vars, 0, sizeof(*vars));
}
static void codel_stats_init(struct codel_stats *stats)
{
stats->maxpacket = 0;
}
/*
* http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
* new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
*
* Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
*/
static void codel_Newton_step(struct codel_vars *vars)
{
u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
val >>= 2; /* avoid overflow in following multiply */
val = (val * invsqrt) >> (32 - 2 + 1);
vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
}
/*
* CoDel control_law is t + interval/sqrt(count)
* We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid
* both sqrt() and divide operation.
*/
static codel_time_t codel_control_law(codel_time_t t,
codel_time_t interval,
u32 rec_inv_sqrt)
{
return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
}
static bool codel_should_drop(const struct sk_buff *skb,
void *ctx,
struct codel_vars *vars,
struct codel_params *params,
struct codel_stats *stats,
codel_skb_len_t skb_len_func,
codel_skb_time_t skb_time_func,
u32 *backlog,
codel_time_t now)
{
bool ok_to_drop;
u32 skb_len;
if (!skb) {
vars->first_above_time = 0;
return false;
}
skb_len = skb_len_func(skb);
vars->ldelay = now - skb_time_func(skb);
if (unlikely(skb_len > stats->maxpacket))
stats->maxpacket = skb_len;
if (codel_time_before(vars->ldelay, params->target) ||
*backlog <= params->mtu) {
/* went below - stay below for at least interval */
vars->first_above_time = 0;
return false;
}
ok_to_drop = false;
if (vars->first_above_time == 0) {
/* just went above from below. If we stay above
* for at least interval we'll say it's ok to drop
*/
vars->first_above_time = now + params->interval;
} else if (codel_time_after(now, vars->first_above_time)) {
ok_to_drop = true;
}
return ok_to_drop;
}
static struct sk_buff *codel_dequeue(void *ctx,
u32 *backlog,
struct codel_params *params,
struct codel_vars *vars,
struct codel_stats *stats,
codel_skb_len_t skb_len_func,
codel_skb_time_t skb_time_func,
codel_skb_drop_t drop_func,
codel_skb_dequeue_t dequeue_func)
{
struct sk_buff *skb = dequeue_func(vars, ctx);
codel_time_t now;
bool drop;
if (!skb) {
vars->dropping = false;
return skb;
}
now = codel_get_time();
drop = codel_should_drop(skb, ctx, vars, params, stats,
skb_len_func, skb_time_func, backlog, now);
if (vars->dropping) {
if (!drop) {
/* sojourn time below target - leave dropping state */
vars->dropping = false;
} else if (codel_time_after_eq(now, vars->drop_next)) {
/* It's time for the next drop. Drop the current
* packet and dequeue the next. The dequeue might
* take us out of dropping state.
* If not, schedule the next drop.
* A large backlog might result in drop rates so high
* that the next drop should happen now,
* hence the while loop.
*/
while (vars->dropping &&
codel_time_after_eq(now, vars->drop_next)) {
vars->count++; /* dont care of possible wrap
* since there is no more divide
*/
codel_Newton_step(vars);
if (params->ecn && INET_ECN_set_ce(skb)) {
stats->ecn_mark++;
vars->drop_next =
codel_control_law(vars->drop_next,
params->interval,
vars->rec_inv_sqrt);
goto end;
}
stats->drop_len += skb_len_func(skb);
drop_func(skb, ctx);
stats->drop_count++;
skb = dequeue_func(vars, ctx);
if (!codel_should_drop(skb, ctx,
vars, params, stats,
skb_len_func,
skb_time_func,
backlog, now)) {
/* leave dropping state */
vars->dropping = false;
} else {
/* and schedule the next drop */
vars->drop_next =
codel_control_law(vars->drop_next,
params->interval,
vars->rec_inv_sqrt);
}
}
}
} else if (drop) {
u32 delta;
if (params->ecn && INET_ECN_set_ce(skb)) {
stats->ecn_mark++;
} else {
stats->drop_len += skb_len_func(skb);
drop_func(skb, ctx);
stats->drop_count++;
skb = dequeue_func(vars, ctx);
drop = codel_should_drop(skb, ctx, vars, params,
stats, skb_len_func,
skb_time_func, backlog, now);
}
vars->dropping = true;
/* if min went above target close to when we last went below it
* assume that the drop rate that controlled the queue on the
* last cycle is a good starting point to control it now.
*/
delta = vars->count - vars->lastcount;
if (delta > 1 &&
codel_time_before(now - vars->drop_next,
16 * params->interval)) {
vars->count = delta;
/* we dont care if rec_inv_sqrt approximation
* is not very precise :
* Next Newton steps will correct it quadratically.
*/
codel_Newton_step(vars);
} else {
vars->count = 1;
vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
}
vars->lastcount = vars->count;
vars->drop_next = codel_control_law(now, params->interval,
vars->rec_inv_sqrt);
}
end:
if (skb && codel_time_after(vars->ldelay, params->ce_threshold) &&
INET_ECN_set_ce(skb))
stats->ce_mark++;
return skb;
}
#endif
+74
View File
@@ -0,0 +1,74 @@
#ifndef __NET_SCHED_CODEL_QDISC_H
#define __NET_SCHED_CODEL_QDISC_H
/*
* Codel - The Controlled-Delay Active Queue Management algorithm
*
* Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
* Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
* Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
* Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
/* Controlling Queue Delay (CoDel) algorithm
* =========================================
* Source : Kathleen Nichols and Van Jacobson
* http://queue.acm.org/detail.cfm?id=2209336
*
* Implemented on linux by Dave Taht and Eric Dumazet
*/
/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */
struct codel_skb_cb {
codel_time_t enqueue_time;
unsigned int mem_usage;
};
static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb)
{
qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb));
return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data;
}
static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb)
{
return get_codel_cb(skb)->enqueue_time;
}
static void codel_set_enqueue_time(struct sk_buff *skb)
{
get_codel_cb(skb)->enqueue_time = codel_get_time();
}
#endif
+59
View File
@@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef NET_COMPAT_H
#define NET_COMPAT_H
struct sock;
#if defined(CONFIG_COMPAT)
#include <linux/compat.h>
struct compat_msghdr {
compat_uptr_t msg_name; /* void * */
compat_int_t msg_namelen;
compat_uptr_t msg_iov; /* struct compat_iovec * */
compat_size_t msg_iovlen;
compat_uptr_t msg_control; /* void * */
compat_size_t msg_controllen;
compat_uint_t msg_flags;
};
struct compat_mmsghdr {
struct compat_msghdr msg_hdr;
compat_uint_t msg_len;
};
struct compat_cmsghdr {
compat_size_t cmsg_len;
compat_int_t cmsg_level;
compat_int_t cmsg_type;
};
int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
#else /* defined(CONFIG_COMPAT) */
/*
* To avoid compiler warnings:
*/
#define compat_msghdr msghdr
#define compat_mmsghdr mmsghdr
#endif /* defined(CONFIG_COMPAT) */
int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
struct sockaddr __user **, struct iovec **);
struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval);
int put_cmsg_compat(struct msghdr*, int, int, int, void *);
int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *,
unsigned char *, int);
int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int,
int (*)(struct sock *, int, int, char __user *,
unsigned int));
int compat_mc_getsockopt(struct sock *, int, int, char __user *, int __user *,
int (*)(struct sock *, int, int, char __user *,
int __user *));
#endif /* NET_COMPAT_H */
+21
View File
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_INET_DATALINK_H_
#define _NET_INET_DATALINK_H_
struct datalink_proto {
unsigned char type[8];
struct llc_sap *sap;
unsigned short header_length;
int (*rcvfunc)(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
int (*request)(struct datalink_proto *, struct sk_buff *,
unsigned char *);
struct list_head node;
};
struct datalink_proto *make_EII_client(void);
void destroy_EII_client(struct datalink_proto *dl);
#endif
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2010, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: John Fastabend <john.r.fastabend@intel.com>
*/
#ifndef _DCB_EVENT_H
#define _DCB_EVENT_H
enum dcbevent_notif_type {
DCB_APP_EVENT = 1,
};
#ifdef CONFIG_DCB
int register_dcbevent_notifier(struct notifier_block *nb);
int unregister_dcbevent_notifier(struct notifier_block *nb);
int call_dcbevent_notifiers(unsigned long val, void *v);
#else
static inline int
register_dcbevent_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int unregister_dcbevent_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int call_dcbevent_notifiers(unsigned long val, void *v)
{
return 0;
}
#endif /* CONFIG_DCB */
#endif
+123
View File
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2008, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Lucy Liu <lucy.liu@intel.com>
*/
#ifndef __NET_DCBNL_H__
#define __NET_DCBNL_H__
#include <linux/dcbnl.h>
struct dcb_app_type {
int ifindex;
struct dcb_app app;
struct list_head list;
u8 dcbx;
};
int dcb_setapp(struct net_device *, struct dcb_app *);
u8 dcb_getapp(struct net_device *, struct dcb_app *);
int dcb_ieee_setapp(struct net_device *, struct dcb_app *);
int dcb_ieee_delapp(struct net_device *, struct dcb_app *);
u8 dcb_ieee_getapp_mask(struct net_device *, struct dcb_app *);
struct dcb_ieee_app_prio_map {
u64 map[IEEE_8021QAZ_MAX_TCS];
};
void dcb_ieee_getapp_prio_dscp_mask_map(const struct net_device *dev,
struct dcb_ieee_app_prio_map *p_map);
struct dcb_ieee_app_dscp_map {
u8 map[64];
};
void dcb_ieee_getapp_dscp_prio_mask_map(const struct net_device *dev,
struct dcb_ieee_app_dscp_map *p_map);
u8 dcb_ieee_getapp_default_prio_mask(const struct net_device *dev);
int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
u32 seq, u32 pid);
int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
u32 seq, u32 pid);
/*
* Ops struct for the netlink callbacks. Used by DCB-enabled drivers through
* the netdevice struct.
*/
struct dcbnl_rtnl_ops {
/* IEEE 802.1Qaz std */
int (*ieee_getets) (struct net_device *, struct ieee_ets *);
int (*ieee_setets) (struct net_device *, struct ieee_ets *);
int (*ieee_getmaxrate) (struct net_device *, struct ieee_maxrate *);
int (*ieee_setmaxrate) (struct net_device *, struct ieee_maxrate *);
int (*ieee_getqcn) (struct net_device *, struct ieee_qcn *);
int (*ieee_setqcn) (struct net_device *, struct ieee_qcn *);
int (*ieee_getqcnstats) (struct net_device *, struct ieee_qcn_stats *);
int (*ieee_getpfc) (struct net_device *, struct ieee_pfc *);
int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
int (*ieee_getapp) (struct net_device *, struct dcb_app *);
int (*ieee_setapp) (struct net_device *, struct dcb_app *);
int (*ieee_delapp) (struct net_device *, struct dcb_app *);
int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *);
int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *);
/* CEE std */
u8 (*getstate)(struct net_device *);
u8 (*setstate)(struct net_device *, u8);
void (*getpermhwaddr)(struct net_device *, u8 *);
void (*setpgtccfgtx)(struct net_device *, int, u8, u8, u8, u8);
void (*setpgbwgcfgtx)(struct net_device *, int, u8);
void (*setpgtccfgrx)(struct net_device *, int, u8, u8, u8, u8);
void (*setpgbwgcfgrx)(struct net_device *, int, u8);
void (*getpgtccfgtx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
void (*getpgbwgcfgtx)(struct net_device *, int, u8 *);
void (*getpgtccfgrx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
void (*getpgbwgcfgrx)(struct net_device *, int, u8 *);
void (*setpfccfg)(struct net_device *, int, u8);
void (*getpfccfg)(struct net_device *, int, u8 *);
u8 (*setall)(struct net_device *);
u8 (*getcap)(struct net_device *, int, u8 *);
int (*getnumtcs)(struct net_device *, int, u8 *);
int (*setnumtcs)(struct net_device *, int, u8);
u8 (*getpfcstate)(struct net_device *);
void (*setpfcstate)(struct net_device *, u8);
void (*getbcncfg)(struct net_device *, int, u32 *);
void (*setbcncfg)(struct net_device *, int, u32);
void (*getbcnrp)(struct net_device *, int, u8 *);
void (*setbcnrp)(struct net_device *, int, u8);
int (*setapp)(struct net_device *, u8, u16, u8);
int (*getapp)(struct net_device *, u8, u16);
u8 (*getfeatcfg)(struct net_device *, int, u8 *);
u8 (*setfeatcfg)(struct net_device *, int, u8);
/* DCBX configuration */
u8 (*getdcbx)(struct net_device *);
u8 (*setdcbx)(struct net_device *, u8);
/* peer apps */
int (*peer_getappinfo)(struct net_device *, struct dcb_peer_app_info *,
u16 *);
int (*peer_getapptable)(struct net_device *, struct dcb_app *);
/* CEE peer */
int (*cee_peer_getpg) (struct net_device *, struct cee_pg *);
int (*cee_peer_getpfc) (struct net_device *, struct cee_pfc *);
/* buffer settings */
int (*dcbnl_getbuffer)(struct net_device *, struct dcbnl_buffer *);
int (*dcbnl_setbuffer)(struct net_device *, struct dcbnl_buffer *);
};
#endif /* __NET_DCBNL_H__ */
+830
View File
@@ -0,0 +1,830 @@
/*
* include/net/devlink.h - Network physical device Netlink interface
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
* Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _NET_DEVLINK_H_
#define _NET_DEVLINK_H_
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <uapi/linux/devlink.h>
struct devlink_ops;
struct devlink {
struct list_head list;
struct list_head port_list;
struct list_head sb_list;
struct list_head dpipe_table_list;
struct list_head resource_list;
struct list_head param_list;
struct list_head region_list;
u32 snapshot_id;
struct devlink_dpipe_headers *dpipe_headers;
const struct devlink_ops *ops;
struct device *dev;
possible_net_t _net;
struct mutex lock;
char priv[0] __aligned(NETDEV_ALIGN);
};
struct devlink_port_attrs {
bool set;
enum devlink_port_flavour flavour;
u32 port_number; /* same value as "split group" */
bool split;
u32 split_subport_number;
};
struct devlink_port {
struct list_head list;
struct devlink *devlink;
unsigned index;
bool registered;
enum devlink_port_type type;
enum devlink_port_type desired_type;
void *type_dev;
struct devlink_port_attrs attrs;
};
struct devlink_sb_pool_info {
enum devlink_sb_pool_type pool_type;
u32 size;
enum devlink_sb_threshold_type threshold_type;
};
/**
* struct devlink_dpipe_field - dpipe field object
* @name: field name
* @id: index inside the headers field array
* @bitwidth: bitwidth
* @mapping_type: mapping type
*/
struct devlink_dpipe_field {
const char *name;
unsigned int id;
unsigned int bitwidth;
enum devlink_dpipe_field_mapping_type mapping_type;
};
/**
* struct devlink_dpipe_header - dpipe header object
* @name: header name
* @id: index, global/local detrmined by global bit
* @fields: fields
* @fields_count: number of fields
* @global: indicates if header is shared like most protocol header
* or driver specific
*/
struct devlink_dpipe_header {
const char *name;
unsigned int id;
struct devlink_dpipe_field *fields;
unsigned int fields_count;
bool global;
};
/**
* struct devlink_dpipe_match - represents match operation
* @type: type of match
* @header_index: header index (packets can have several headers of same
* type like in case of tunnels)
* @header: header
* @fieled_id: field index
*/
struct devlink_dpipe_match {
enum devlink_dpipe_match_type type;
unsigned int header_index;
struct devlink_dpipe_header *header;
unsigned int field_id;
};
/**
* struct devlink_dpipe_action - represents action operation
* @type: type of action
* @header_index: header index (packets can have several headers of same
* type like in case of tunnels)
* @header: header
* @fieled_id: field index
*/
struct devlink_dpipe_action {
enum devlink_dpipe_action_type type;
unsigned int header_index;
struct devlink_dpipe_header *header;
unsigned int field_id;
};
/**
* struct devlink_dpipe_value - represents value of match/action
* @action: action
* @match: match
* @mapping_value: in case the field has some mapping this value
* specified the mapping value
* @mapping_valid: specify if mapping value is valid
* @value_size: value size
* @value: value
* @mask: bit mask
*/
struct devlink_dpipe_value {
union {
struct devlink_dpipe_action *action;
struct devlink_dpipe_match *match;
};
unsigned int mapping_value;
bool mapping_valid;
unsigned int value_size;
void *value;
void *mask;
};
/**
* struct devlink_dpipe_entry - table entry object
* @index: index of the entry in the table
* @match_values: match values
* @matche_values_count: count of matches tuples
* @action_values: actions values
* @action_values_count: count of actions values
* @counter: value of counter
* @counter_valid: Specify if value is valid from hardware
*/
struct devlink_dpipe_entry {
u64 index;
struct devlink_dpipe_value *match_values;
unsigned int match_values_count;
struct devlink_dpipe_value *action_values;
unsigned int action_values_count;
u64 counter;
bool counter_valid;
};
/**
* struct devlink_dpipe_dump_ctx - context provided to driver in order
* to dump
* @info: info
* @cmd: devlink command
* @skb: skb
* @nest: top attribute
* @hdr: hdr
*/
struct devlink_dpipe_dump_ctx {
struct genl_info *info;
enum devlink_command cmd;
struct sk_buff *skb;
struct nlattr *nest;
void *hdr;
};
struct devlink_dpipe_table_ops;
/**
* struct devlink_dpipe_table - table object
* @priv: private
* @name: table name
* @counters_enabled: indicates if counters are active
* @counter_control_extern: indicates if counter control is in dpipe or
* external tool
* @resource_valid: Indicate that the resource id is valid
* @resource_id: relative resource this table is related to
* @resource_units: number of resource's unit consumed per table's entry
* @table_ops: table operations
* @rcu: rcu
*/
struct devlink_dpipe_table {
void *priv;
struct list_head list;
const char *name;
bool counters_enabled;
bool counter_control_extern;
bool resource_valid;
u64 resource_id;
u64 resource_units;
struct devlink_dpipe_table_ops *table_ops;
struct rcu_head rcu;
};
/**
* struct devlink_dpipe_table_ops - dpipe_table ops
* @actions_dump - dumps all tables actions
* @matches_dump - dumps all tables matches
* @entries_dump - dumps all active entries in the table
* @counters_set_update - when changing the counter status hardware sync
* maybe needed to allocate/free counter related
* resources
* @size_get - get size
*/
struct devlink_dpipe_table_ops {
int (*actions_dump)(void *priv, struct sk_buff *skb);
int (*matches_dump)(void *priv, struct sk_buff *skb);
int (*entries_dump)(void *priv, bool counters_enabled,
struct devlink_dpipe_dump_ctx *dump_ctx);
int (*counters_set_update)(void *priv, bool enable);
u64 (*size_get)(void *priv);
};
/**
* struct devlink_dpipe_headers - dpipe headers
* @headers - header array can be shared (global bit) or driver specific
* @headers_count - count of headers
*/
struct devlink_dpipe_headers {
struct devlink_dpipe_header **headers;
unsigned int headers_count;
};
/**
* struct devlink_resource_size_params - resource's size parameters
* @size_min: minimum size which can be set
* @size_max: maximum size which can be set
* @size_granularity: size granularity
* @size_unit: resource's basic unit
*/
struct devlink_resource_size_params {
u64 size_min;
u64 size_max;
u64 size_granularity;
enum devlink_resource_unit unit;
};
static inline void
devlink_resource_size_params_init(struct devlink_resource_size_params *size_params,
u64 size_min, u64 size_max,
u64 size_granularity,
enum devlink_resource_unit unit)
{
size_params->size_min = size_min;
size_params->size_max = size_max;
size_params->size_granularity = size_granularity;
size_params->unit = unit;
}
typedef u64 devlink_resource_occ_get_t(void *priv);
/**
* struct devlink_resource - devlink resource
* @name: name of the resource
* @id: id, per devlink instance
* @size: size of the resource
* @size_new: updated size of the resource, reload is needed
* @size_valid: valid in case the total size of the resource is valid
* including its children
* @parent: parent resource
* @size_params: size parameters
* @list: parent list
* @resource_list: list of child resources
*/
struct devlink_resource {
const char *name;
u64 id;
u64 size;
u64 size_new;
bool size_valid;
struct devlink_resource *parent;
struct devlink_resource_size_params size_params;
struct list_head list;
struct list_head resource_list;
devlink_resource_occ_get_t *occ_get;
void *occ_get_priv;
};
#define DEVLINK_RESOURCE_ID_PARENT_TOP 0
#define __DEVLINK_PARAM_MAX_STRING_VALUE 32
enum devlink_param_type {
DEVLINK_PARAM_TYPE_U8,
DEVLINK_PARAM_TYPE_U16,
DEVLINK_PARAM_TYPE_U32,
DEVLINK_PARAM_TYPE_STRING,
DEVLINK_PARAM_TYPE_BOOL,
};
union devlink_param_value {
u8 vu8;
u16 vu16;
u32 vu32;
char vstr[__DEVLINK_PARAM_MAX_STRING_VALUE];
bool vbool;
};
struct devlink_param_gset_ctx {
union devlink_param_value val;
enum devlink_param_cmode cmode;
};
/**
* struct devlink_param - devlink configuration parameter data
* @name: name of the parameter
* @generic: indicates if the parameter is generic or driver specific
* @type: parameter type
* @supported_cmodes: bitmap of supported configuration modes
* @get: get parameter value, used for runtime and permanent
* configuration modes
* @set: set parameter value, used for runtime and permanent
* configuration modes
* @validate: validate input value is applicable (within value range, etc.)
*
* This struct should be used by the driver to fill the data for
* a parameter it registers.
*/
struct devlink_param {
u32 id;
const char *name;
bool generic;
enum devlink_param_type type;
unsigned long supported_cmodes;
int (*get)(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx);
int (*set)(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx);
int (*validate)(struct devlink *devlink, u32 id,
union devlink_param_value val,
struct netlink_ext_ack *extack);
};
struct devlink_param_item {
struct list_head list;
const struct devlink_param *param;
union devlink_param_value driverinit_value;
bool driverinit_value_valid;
};
enum devlink_param_generic_id {
DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
/* add new param generic ids above here*/
__DEVLINK_PARAM_GENERIC_ID_MAX,
DEVLINK_PARAM_GENERIC_ID_MAX = __DEVLINK_PARAM_GENERIC_ID_MAX - 1,
};
#define DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME "internal_error_reset"
#define DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE DEVLINK_PARAM_TYPE_BOOL
#define DEVLINK_PARAM_GENERIC_MAX_MACS_NAME "max_macs"
#define DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE DEVLINK_PARAM_TYPE_U32
#define DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME "enable_sriov"
#define DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE DEVLINK_PARAM_TYPE_BOOL
#define DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME "region_snapshot_enable"
#define DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE DEVLINK_PARAM_TYPE_BOOL
#define DEVLINK_PARAM_GENERIC(_id, _cmodes, _get, _set, _validate) \
{ \
.id = DEVLINK_PARAM_GENERIC_ID_##_id, \
.name = DEVLINK_PARAM_GENERIC_##_id##_NAME, \
.type = DEVLINK_PARAM_GENERIC_##_id##_TYPE, \
.generic = true, \
.supported_cmodes = _cmodes, \
.get = _get, \
.set = _set, \
.validate = _validate, \
}
#define DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes, _get, _set, _validate) \
{ \
.id = _id, \
.name = _name, \
.type = _type, \
.supported_cmodes = _cmodes, \
.get = _get, \
.set = _set, \
.validate = _validate, \
}
struct devlink_region;
typedef void devlink_snapshot_data_dest_t(const void *data);
struct devlink_ops {
int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack);
int (*port_type_set)(struct devlink_port *devlink_port,
enum devlink_port_type port_type);
int (*port_split)(struct devlink *devlink, unsigned int port_index,
unsigned int count, struct netlink_ext_ack *extack);
int (*port_unsplit)(struct devlink *devlink, unsigned int port_index,
struct netlink_ext_ack *extack);
int (*sb_pool_get)(struct devlink *devlink, unsigned int sb_index,
u16 pool_index,
struct devlink_sb_pool_info *pool_info);
int (*sb_pool_set)(struct devlink *devlink, unsigned int sb_index,
u16 pool_index, u32 size,
enum devlink_sb_threshold_type threshold_type);
int (*sb_port_pool_get)(struct devlink_port *devlink_port,
unsigned int sb_index, u16 pool_index,
u32 *p_threshold);
int (*sb_port_pool_set)(struct devlink_port *devlink_port,
unsigned int sb_index, u16 pool_index,
u32 threshold);
int (*sb_tc_pool_bind_get)(struct devlink_port *devlink_port,
unsigned int sb_index,
u16 tc_index,
enum devlink_sb_pool_type pool_type,
u16 *p_pool_index, u32 *p_threshold);
int (*sb_tc_pool_bind_set)(struct devlink_port *devlink_port,
unsigned int sb_index,
u16 tc_index,
enum devlink_sb_pool_type pool_type,
u16 pool_index, u32 threshold);
int (*sb_occ_snapshot)(struct devlink *devlink,
unsigned int sb_index);
int (*sb_occ_max_clear)(struct devlink *devlink,
unsigned int sb_index);
int (*sb_occ_port_pool_get)(struct devlink_port *devlink_port,
unsigned int sb_index, u16 pool_index,
u32 *p_cur, u32 *p_max);
int (*sb_occ_tc_port_bind_get)(struct devlink_port *devlink_port,
unsigned int sb_index,
u16 tc_index,
enum devlink_sb_pool_type pool_type,
u32 *p_cur, u32 *p_max);
int (*eswitch_mode_get)(struct devlink *devlink, u16 *p_mode);
int (*eswitch_mode_set)(struct devlink *devlink, u16 mode);
int (*eswitch_inline_mode_get)(struct devlink *devlink, u8 *p_inline_mode);
int (*eswitch_inline_mode_set)(struct devlink *devlink, u8 inline_mode);
int (*eswitch_encap_mode_get)(struct devlink *devlink, u8 *p_encap_mode);
int (*eswitch_encap_mode_set)(struct devlink *devlink, u8 encap_mode);
};
static inline void *devlink_priv(struct devlink *devlink)
{
BUG_ON(!devlink);
return &devlink->priv;
}
static inline struct devlink *priv_to_devlink(void *priv)
{
BUG_ON(!priv);
return container_of(priv, struct devlink, priv);
}
struct ib_device;
#if IS_ENABLED(CONFIG_NET_DEVLINK)
struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size);
int devlink_register(struct devlink *devlink, struct device *dev);
void devlink_unregister(struct devlink *devlink);
void devlink_free(struct devlink *devlink);
int devlink_port_register(struct devlink *devlink,
struct devlink_port *devlink_port,
unsigned int port_index);
void devlink_port_unregister(struct devlink_port *devlink_port);
void devlink_port_type_eth_set(struct devlink_port *devlink_port,
struct net_device *netdev);
void devlink_port_type_ib_set(struct devlink_port *devlink_port,
struct ib_device *ibdev);
void devlink_port_type_clear(struct devlink_port *devlink_port);
void devlink_port_attrs_set(struct devlink_port *devlink_port,
enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number);
int devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
char *name, size_t len);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count,
u16 egress_pools_count, u16 ingress_tc_count,
u16 egress_tc_count);
void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index);
int devlink_dpipe_table_register(struct devlink *devlink,
const char *table_name,
struct devlink_dpipe_table_ops *table_ops,
void *priv, bool counter_control_extern);
void devlink_dpipe_table_unregister(struct devlink *devlink,
const char *table_name);
int devlink_dpipe_headers_register(struct devlink *devlink,
struct devlink_dpipe_headers *dpipe_headers);
void devlink_dpipe_headers_unregister(struct devlink *devlink);
bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
const char *table_name);
int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx);
int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
struct devlink_dpipe_entry *entry);
int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx);
void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry);
int devlink_dpipe_action_put(struct sk_buff *skb,
struct devlink_dpipe_action *action);
int devlink_dpipe_match_put(struct sk_buff *skb,
struct devlink_dpipe_match *match);
extern struct devlink_dpipe_header devlink_dpipe_header_ethernet;
extern struct devlink_dpipe_header devlink_dpipe_header_ipv4;
extern struct devlink_dpipe_header devlink_dpipe_header_ipv6;
int devlink_resource_register(struct devlink *devlink,
const char *resource_name,
u64 resource_size,
u64 resource_id,
u64 parent_resource_id,
const struct devlink_resource_size_params *size_params);
void devlink_resources_unregister(struct devlink *devlink,
struct devlink_resource *resource);
int devlink_resource_size_get(struct devlink *devlink,
u64 resource_id,
u64 *p_resource_size);
int devlink_dpipe_table_resource_set(struct devlink *devlink,
const char *table_name, u64 resource_id,
u64 resource_units);
void devlink_resource_occ_get_register(struct devlink *devlink,
u64 resource_id,
devlink_resource_occ_get_t *occ_get,
void *occ_get_priv);
void devlink_resource_occ_get_unregister(struct devlink *devlink,
u64 resource_id);
int devlink_params_register(struct devlink *devlink,
const struct devlink_param *params,
size_t params_count);
void devlink_params_unregister(struct devlink *devlink,
const struct devlink_param *params,
size_t params_count);
int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
union devlink_param_value *init_val);
int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
union devlink_param_value init_val);
void devlink_param_value_changed(struct devlink *devlink, u32 param_id);
void devlink_param_value_str_fill(union devlink_param_value *dst_val,
const char *src);
struct devlink_region *devlink_region_create(struct devlink *devlink,
const char *region_name,
u32 region_max_snapshots,
u64 region_size);
void devlink_region_destroy(struct devlink_region *region);
u32 devlink_region_shapshot_id_get(struct devlink *devlink);
int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
u8 *data, u32 snapshot_id,
devlink_snapshot_data_dest_t *data_destructor);
#else
static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,
size_t priv_size)
{
return kzalloc(sizeof(struct devlink) + priv_size, GFP_KERNEL);
}
static inline int devlink_register(struct devlink *devlink, struct device *dev)
{
return 0;
}
static inline void devlink_unregister(struct devlink *devlink)
{
}
static inline void devlink_free(struct devlink *devlink)
{
kfree(devlink);
}
static inline int devlink_port_register(struct devlink *devlink,
struct devlink_port *devlink_port,
unsigned int port_index)
{
return 0;
}
static inline void devlink_port_unregister(struct devlink_port *devlink_port)
{
}
static inline void devlink_port_type_eth_set(struct devlink_port *devlink_port,
struct net_device *netdev)
{
}
static inline void devlink_port_type_ib_set(struct devlink_port *devlink_port,
struct ib_device *ibdev)
{
}
static inline void devlink_port_type_clear(struct devlink_port *devlink_port)
{
}
static inline void devlink_port_attrs_set(struct devlink_port *devlink_port,
enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number)
{
}
static inline int
devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
char *name, size_t len)
{
return -EOPNOTSUPP;
}
static inline int devlink_sb_register(struct devlink *devlink,
unsigned int sb_index, u32 size,
u16 ingress_pools_count,
u16 egress_pools_count,
u16 ingress_tc_count,
u16 egress_tc_count)
{
return 0;
}
static inline void devlink_sb_unregister(struct devlink *devlink,
unsigned int sb_index)
{
}
static inline int
devlink_dpipe_table_register(struct devlink *devlink,
const char *table_name,
struct devlink_dpipe_table_ops *table_ops,
void *priv, bool counter_control_extern)
{
return 0;
}
static inline void devlink_dpipe_table_unregister(struct devlink *devlink,
const char *table_name)
{
}
static inline int devlink_dpipe_headers_register(struct devlink *devlink,
struct devlink_dpipe_headers *
dpipe_headers)
{
return 0;
}
static inline void devlink_dpipe_headers_unregister(struct devlink *devlink)
{
}
static inline bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
const char *table_name)
{
return false;
}
static inline int
devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
{
return 0;
}
static inline int
devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
struct devlink_dpipe_entry *entry)
{
return 0;
}
static inline int
devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
{
return 0;
}
static inline void
devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
{
}
static inline int
devlink_dpipe_action_put(struct sk_buff *skb,
struct devlink_dpipe_action *action)
{
return 0;
}
static inline int
devlink_dpipe_match_put(struct sk_buff *skb,
struct devlink_dpipe_match *match)
{
return 0;
}
static inline int
devlink_resource_register(struct devlink *devlink,
const char *resource_name,
u64 resource_size,
u64 resource_id,
u64 parent_resource_id,
const struct devlink_resource_size_params *size_params)
{
return 0;
}
static inline void
devlink_resources_unregister(struct devlink *devlink,
struct devlink_resource *resource)
{
}
static inline int
devlink_resource_size_get(struct devlink *devlink, u64 resource_id,
u64 *p_resource_size)
{
return -EOPNOTSUPP;
}
static inline int
devlink_dpipe_table_resource_set(struct devlink *devlink,
const char *table_name, u64 resource_id,
u64 resource_units)
{
return -EOPNOTSUPP;
}
static inline void
devlink_resource_occ_get_register(struct devlink *devlink,
u64 resource_id,
devlink_resource_occ_get_t *occ_get,
void *occ_get_priv)
{
}
static inline void
devlink_resource_occ_get_unregister(struct devlink *devlink,
u64 resource_id)
{
}
static inline int
devlink_params_register(struct devlink *devlink,
const struct devlink_param *params,
size_t params_count)
{
return 0;
}
static inline void
devlink_params_unregister(struct devlink *devlink,
const struct devlink_param *params,
size_t params_count)
{
}
static inline int
devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
union devlink_param_value *init_val)
{
return -EOPNOTSUPP;
}
static inline int
devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
union devlink_param_value init_val)
{
return -EOPNOTSUPP;
}
static inline void
devlink_param_value_changed(struct devlink *devlink, u32 param_id)
{
}
static inline void
devlink_param_value_str_fill(union devlink_param_value *dst_val,
const char *src)
{
}
static inline struct devlink_region *
devlink_region_create(struct devlink *devlink,
const char *region_name,
u32 region_max_snapshots,
u64 region_size)
{
return NULL;
}
static inline void
devlink_region_destroy(struct devlink_region *region)
{
}
static inline u32
devlink_region_shapshot_id_get(struct devlink *devlink)
{
return 0;
}
static inline int
devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
u8 *data, u32 snapshot_id,
devlink_snapshot_data_dest_t *data_destructor)
{
return 0;
}
#endif
#endif /* _NET_DEVLINK_H_ */
+231
View File
@@ -0,0 +1,231 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_DN_H
#define _NET_DN_H
#include <linux/dn.h>
#include <net/sock.h>
#include <net/flow.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
struct dn_scp /* Session Control Port */
{
unsigned char state;
#define DN_O 1 /* Open */
#define DN_CR 2 /* Connect Receive */
#define DN_DR 3 /* Disconnect Reject */
#define DN_DRC 4 /* Discon. Rej. Complete*/
#define DN_CC 5 /* Connect Confirm */
#define DN_CI 6 /* Connect Initiate */
#define DN_NR 7 /* No resources */
#define DN_NC 8 /* No communication */
#define DN_CD 9 /* Connect Delivery */
#define DN_RJ 10 /* Rejected */
#define DN_RUN 11 /* Running */
#define DN_DI 12 /* Disconnect Initiate */
#define DN_DIC 13 /* Disconnect Complete */
#define DN_DN 14 /* Disconnect Notificat */
#define DN_CL 15 /* Closed */
#define DN_CN 16 /* Closed Notification */
__le16 addrloc;
__le16 addrrem;
__u16 numdat;
__u16 numoth;
__u16 numoth_rcv;
__u16 numdat_rcv;
__u16 ackxmt_dat;
__u16 ackxmt_oth;
__u16 ackrcv_dat;
__u16 ackrcv_oth;
__u8 flowrem_sw;
__u8 flowloc_sw;
#define DN_SEND 2
#define DN_DONTSEND 1
#define DN_NOCHANGE 0
__u16 flowrem_dat;
__u16 flowrem_oth;
__u16 flowloc_dat;
__u16 flowloc_oth;
__u8 services_rem;
__u8 services_loc;
__u8 info_rem;
__u8 info_loc;
__u16 segsize_rem;
__u16 segsize_loc;
__u8 nonagle;
__u8 multi_ireq;
__u8 accept_mode;
unsigned long seg_total; /* Running total of current segment */
struct optdata_dn conndata_in;
struct optdata_dn conndata_out;
struct optdata_dn discdata_in;
struct optdata_dn discdata_out;
struct accessdata_dn accessdata;
struct sockaddr_dn addr; /* Local address */
struct sockaddr_dn peer; /* Remote address */
/*
* In this case the RTT estimation is not specified in the
* docs, nor is any back off algorithm. Here we follow well
* known tcp algorithms with a few small variations.
*
* snd_window: Max number of packets we send before we wait for
* an ack to come back. This will become part of a
* more complicated scheme when we support flow
* control.
*
* nsp_srtt: Round-Trip-Time (x8) in jiffies. This is a rolling
* average.
* nsp_rttvar: Round-Trip-Time-Varience (x4) in jiffies. This is the
* varience of the smoothed average (but calculated in
* a simpler way than for normal statistical varience
* calculations).
*
* nsp_rxtshift: Backoff counter. Value is zero normally, each time
* a packet is lost is increases by one until an ack
* is received. Its used to index an array of backoff
* multipliers.
*/
#define NSP_MIN_WINDOW 1
#define NSP_MAX_WINDOW (0x07fe)
unsigned long max_window;
unsigned long snd_window;
#define NSP_INITIAL_SRTT (HZ)
unsigned long nsp_srtt;
#define NSP_INITIAL_RTTVAR (HZ*3)
unsigned long nsp_rttvar;
#define NSP_MAXRXTSHIFT 12
unsigned long nsp_rxtshift;
/*
* Output queues, one for data, one for otherdata/linkservice
*/
struct sk_buff_head data_xmit_queue;
struct sk_buff_head other_xmit_queue;
/*
* Input queue for other data
*/
struct sk_buff_head other_receive_queue;
int other_report;
/*
* Stuff to do with the slow timer
*/
unsigned long stamp; /* time of last transmit */
unsigned long persist;
int (*persist_fxn)(struct sock *sk);
unsigned long keepalive;
void (*keepalive_fxn)(struct sock *sk);
};
static inline struct dn_scp *DN_SK(struct sock *sk)
{
return (struct dn_scp *)(sk + 1);
}
/*
* src,dst : Source and Destination DECnet addresses
* hops : Number of hops through the network
* dst_port, src_port : NSP port numbers
* services, info : Useful data extracted from conninit messages
* rt_flags : Routing flags byte
* nsp_flags : NSP layer flags byte
* segsize : Size of segment
* segnum : Number, for data, otherdata and linkservice
* xmit_count : Number of times we've transmitted this skb
* stamp : Time stamp of most recent transmission, used in RTT calculations
* iif: Input interface number
*
* As a general policy, this structure keeps all addresses in network
* byte order, and all else in host byte order. Thus dst, src, dst_port
* and src_port are in network order. All else is in host order.
*
*/
#define DN_SKB_CB(skb) ((struct dn_skb_cb *)(skb)->cb)
struct dn_skb_cb {
__le16 dst;
__le16 src;
__u16 hops;
__le16 dst_port;
__le16 src_port;
__u8 services;
__u8 info;
__u8 rt_flags;
__u8 nsp_flags;
__u16 segsize;
__u16 segnum;
__u16 xmit_count;
unsigned long stamp;
int iif;
};
static inline __le16 dn_eth2dn(unsigned char *ethaddr)
{
return get_unaligned((__le16 *)(ethaddr + 4));
}
static inline __le16 dn_saddr2dn(struct sockaddr_dn *saddr)
{
return *(__le16 *)saddr->sdn_nodeaddr;
}
static inline void dn_dn2eth(unsigned char *ethaddr, __le16 addr)
{
__u16 a = le16_to_cpu(addr);
ethaddr[0] = 0xAA;
ethaddr[1] = 0x00;
ethaddr[2] = 0x04;
ethaddr[3] = 0x00;
ethaddr[4] = (__u8)(a & 0xff);
ethaddr[5] = (__u8)(a >> 8);
}
static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
{
fld->fld_sport = scp->addrloc;
fld->fld_dport = scp->addrrem;
}
unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu);
void dn_register_sysctl(void);
void dn_unregister_sysctl(void);
#define DN_MENUVER_ACC 0x01
#define DN_MENUVER_USR 0x02
#define DN_MENUVER_PRX 0x04
#define DN_MENUVER_UIC 0x08
struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
struct sock *dn_find_by_skb(struct sk_buff *skb);
#define DN_ASCBUF_LEN 9
char *dn_addr2asc(__u16, char *);
int dn_destroy_timer(struct sock *sk);
int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf,
unsigned char type);
int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr,
unsigned char *type);
void dn_start_slow_timer(struct sock *sk);
void dn_stop_slow_timer(struct sock *sk);
extern __le16 decnet_address;
extern int decnet_debug_level;
extern int decnet_time_wait;
extern int decnet_dn_count;
extern int decnet_di_count;
extern int decnet_dr_count;
extern int decnet_no_fc_max_cwnd;
extern long sysctl_decnet_mem[3];
extern int sysctl_decnet_wmem[3];
extern int sysctl_decnet_rmem[3];
#endif /* _NET_DN_H */
+199
View File
@@ -0,0 +1,199 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_DN_DEV_H
#define _NET_DN_DEV_H
struct dn_dev;
struct dn_ifaddr {
struct dn_ifaddr __rcu *ifa_next;
struct dn_dev *ifa_dev;
__le16 ifa_local;
__le16 ifa_address;
__u32 ifa_flags;
__u8 ifa_scope;
char ifa_label[IFNAMSIZ];
struct rcu_head rcu;
};
#define DN_DEV_S_RU 0 /* Run - working normally */
#define DN_DEV_S_CR 1 /* Circuit Rejected */
#define DN_DEV_S_DS 2 /* Data Link Start */
#define DN_DEV_S_RI 3 /* Routing Layer Initialize */
#define DN_DEV_S_RV 4 /* Routing Layer Verify */
#define DN_DEV_S_RC 5 /* Routing Layer Complete */
#define DN_DEV_S_OF 6 /* Off */
#define DN_DEV_S_HA 7 /* Halt */
/*
* The dn_dev_parms structure contains the set of parameters
* for each device (hence inclusion in the dn_dev structure)
* and an array is used to store the default types of supported
* device (in dn_dev.c).
*
* The type field matches the ARPHRD_ constants and is used in
* searching the list for supported devices when new devices
* come up.
*
* The mode field is used to find out if a device is broadcast,
* multipoint, or pointopoint. Please note that DECnet thinks
* different ways about devices to the rest of the kernel
* so the normal IFF_xxx flags are invalid here. For devices
* which can be any combination of the previously mentioned
* attributes, you can set this on a per device basis by
* installing an up() routine.
*
* The device state field, defines the initial state in which the
* device will come up. In the dn_dev structure, it is the actual
* state.
*
* Things have changed here. I've killed timer1 since it's a user space
* issue for a user space routing deamon to sort out. The kernel does
* not need to be bothered with it.
*
* Timers:
* t2 - Rate limit timer, min time between routing and hello messages
* t3 - Hello timer, send hello messages when it expires
*
* Callbacks:
* up() - Called to initialize device, return value can veto use of
* device with DECnet.
* down() - Called to turn device off when it goes down
* timer3() - Called once for each ifaddr when timer 3 goes off
*
* sysctl - Hook for sysctl things
*
*/
struct dn_dev_parms {
int type; /* ARPHRD_xxx */
int mode; /* Broadcast, Unicast, Mulitpoint */
#define DN_DEV_BCAST 1
#define DN_DEV_UCAST 2
#define DN_DEV_MPOINT 4
int state; /* Initial state */
int forwarding; /* 0=EndNode, 1=L1Router, 2=L2Router */
unsigned long t2; /* Default value of t2 */
unsigned long t3; /* Default value of t3 */
int priority; /* Priority to be a router */
char *name; /* Name for sysctl */
int (*up)(struct net_device *);
void (*down)(struct net_device *);
void (*timer3)(struct net_device *, struct dn_ifaddr *ifa);
void *sysctl;
};
struct dn_dev {
struct dn_ifaddr __rcu *ifa_list;
struct net_device *dev;
struct dn_dev_parms parms;
char use_long;
struct timer_list timer;
unsigned long t3;
struct neigh_parms *neigh_parms;
__u8 addr[ETH_ALEN];
struct neighbour *router; /* Default router on circuit */
struct neighbour *peer; /* Peer on pointopoint links */
unsigned long uptime; /* Time device went up in jiffies */
};
struct dn_short_packet {
__u8 msgflg;
__le16 dstnode;
__le16 srcnode;
__u8 forward;
} __packed;
struct dn_long_packet {
__u8 msgflg;
__u8 d_area;
__u8 d_subarea;
__u8 d_id[6];
__u8 s_area;
__u8 s_subarea;
__u8 s_id[6];
__u8 nl2;
__u8 visit_ct;
__u8 s_class;
__u8 pt;
} __packed;
/*------------------------- DRP - Routing messages ---------------------*/
struct endnode_hello_message {
__u8 msgflg;
__u8 tiver[3];
__u8 id[6];
__u8 iinfo;
__le16 blksize;
__u8 area;
__u8 seed[8];
__u8 neighbor[6];
__le16 timer;
__u8 mpd;
__u8 datalen;
__u8 data[2];
} __packed;
struct rtnode_hello_message {
__u8 msgflg;
__u8 tiver[3];
__u8 id[6];
__u8 iinfo;
__le16 blksize;
__u8 priority;
__u8 area;
__le16 timer;
__u8 mpd;
} __packed;
void dn_dev_init(void);
void dn_dev_cleanup(void);
int dn_dev_ioctl(unsigned int cmd, void __user *arg);
void dn_dev_devices_off(void);
void dn_dev_devices_on(void);
void dn_dev_init_pkt(struct sk_buff *skb);
void dn_dev_veri_pkt(struct sk_buff *skb);
void dn_dev_hello(struct sk_buff *skb);
void dn_dev_up(struct net_device *);
void dn_dev_down(struct net_device *);
int dn_dev_set_default(struct net_device *dev, int force);
struct net_device *dn_dev_get_default(void);
int dn_dev_bind_default(__le16 *addr);
int register_dnaddr_notifier(struct notifier_block *nb);
int unregister_dnaddr_notifier(struct notifier_block *nb);
static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
{
struct dn_dev *dn_db;
struct dn_ifaddr *ifa;
int res = 0;
rcu_read_lock();
dn_db = rcu_dereference(dev->dn_ptr);
if (dn_db == NULL) {
printk(KERN_DEBUG "dn_dev_islocal: Called for non DECnet device\n");
goto out;
}
for (ifa = rcu_dereference(dn_db->ifa_list);
ifa != NULL;
ifa = rcu_dereference(ifa->ifa_next))
if ((addr ^ ifa->ifa_local) == 0) {
res = 1;
break;
}
out:
rcu_read_unlock();
return res;
}
#endif /* _NET_DN_DEV_H */
+167
View File
@@ -0,0 +1,167 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_DN_FIB_H
#define _NET_DN_FIB_H
#include <linux/netlink.h>
#include <linux/refcount.h>
extern const struct nla_policy rtm_dn_policy[];
struct dn_fib_res {
struct fib_rule *r;
struct dn_fib_info *fi;
unsigned char prefixlen;
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
};
struct dn_fib_nh {
struct net_device *nh_dev;
unsigned int nh_flags;
unsigned char nh_scope;
int nh_weight;
int nh_power;
int nh_oif;
__le16 nh_gw;
};
struct dn_fib_info {
struct dn_fib_info *fib_next;
struct dn_fib_info *fib_prev;
int fib_treeref;
refcount_t fib_clntref;
int fib_dead;
unsigned int fib_flags;
int fib_protocol;
__le16 fib_prefsrc;
__u32 fib_priority;
__u32 fib_metrics[RTAX_MAX];
int fib_nhs;
int fib_power;
struct dn_fib_nh fib_nh[0];
#define dn_fib_dev fib_nh[0].nh_dev
};
#define DN_FIB_RES_RESET(res) ((res).nh_sel = 0)
#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
#define DN_FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __dn_fib_res_prefsrc(&res))
#define DN_FIB_RES_GW(res) (DN_FIB_RES_NH(res).nh_gw)
#define DN_FIB_RES_DEV(res) (DN_FIB_RES_NH(res).nh_dev)
#define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif)
typedef struct {
__le16 datum;
} dn_fib_key_t;
typedef struct {
__le16 datum;
} dn_fib_hash_t;
typedef struct {
__u16 datum;
} dn_fib_idx_t;
struct dn_fib_node {
struct dn_fib_node *fn_next;
struct dn_fib_info *fn_info;
#define DN_FIB_INFO(f) ((f)->fn_info)
dn_fib_key_t fn_key;
u8 fn_type;
u8 fn_scope;
u8 fn_state;
};
struct dn_fib_table {
struct hlist_node hlist;
u32 n;
int (*insert)(struct dn_fib_table *t, struct rtmsg *r,
struct nlattr *attrs[], struct nlmsghdr *n,
struct netlink_skb_parms *req);
int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
struct nlattr *attrs[], struct nlmsghdr *n,
struct netlink_skb_parms *req);
int (*lookup)(struct dn_fib_table *t, const struct flowidn *fld,
struct dn_fib_res *res);
int (*flush)(struct dn_fib_table *t);
int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
unsigned char data[0];
};
#ifdef CONFIG_DECNET_ROUTER
/*
* dn_fib.c
*/
void dn_fib_init(void);
void dn_fib_cleanup(void);
int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
struct nlattr *attrs[],
const struct nlmsghdr *nlh, int *errp);
int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
const struct flowidn *fld, struct dn_fib_res *res);
void dn_fib_release_info(struct dn_fib_info *fi);
void dn_fib_flush(void);
void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res);
/*
* dn_tables.c
*/
struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
struct dn_fib_table *dn_fib_empty_table(void);
void dn_fib_table_init(void);
void dn_fib_table_cleanup(void);
/*
* dn_rules.c
*/
void dn_fib_rules_init(void);
void dn_fib_rules_cleanup(void);
unsigned int dnet_addr_type(__le16 addr);
int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res);
int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
void dn_fib_free_info(struct dn_fib_info *fi);
static inline void dn_fib_info_put(struct dn_fib_info *fi)
{
if (refcount_dec_and_test(&fi->fib_clntref))
dn_fib_free_info(fi);
}
static inline void dn_fib_res_put(struct dn_fib_res *res)
{
if (res->fi)
dn_fib_info_put(res->fi);
if (res->r)
fib_rule_put(res->r);
}
#else /* Endnode */
#define dn_fib_init() do { } while(0)
#define dn_fib_cleanup() do { } while(0)
#define dn_fib_lookup(fl, res) (-ESRCH)
#define dn_fib_info_put(fi) do { } while(0)
#define dn_fib_select_multipath(fl, res) do { } while(0)
#define dn_fib_rules_policy(saddr,res,flags) (0)
#define dn_fib_res_put(res) do { } while(0)
#endif /* CONFIG_DECNET_ROUTER */
static inline __le16 dnet_make_mask(int n)
{
if (n)
return cpu_to_le16(~((1 << (16 - n)) - 1));
return cpu_to_le16(0);
}
#endif /* _NET_DN_FIB_H */
+30
View File
@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_DN_NEIGH_H
#define _NET_DN_NEIGH_H
/*
* The position of the first two fields of
* this structure are critical - SJW
*/
struct dn_neigh {
struct neighbour n;
__le16 addr;
unsigned long flags;
#define DN_NDFLAG_R1 0x0001 /* Router L1 */
#define DN_NDFLAG_R2 0x0002 /* Router L2 */
#define DN_NDFLAG_P3 0x0004 /* Phase III Node */
unsigned long blksize;
__u8 priority;
};
void dn_neigh_init(void);
void dn_neigh_cleanup(void);
int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb);
int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb);
void dn_neigh_pointopoint_hello(struct sk_buff *skb);
int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb);
extern struct neigh_table dn_neigh_table;
#endif /* _NET_DN_NEIGH_H */
+203
View File
@@ -0,0 +1,203 @@
#ifndef _NET_DN_NSP_H
#define _NET_DN_NSP_H
/******************************************************************************
(c) 1995-1998 E.M. Serrat emserrat@geocities.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*******************************************************************************/
/* dn_nsp.c functions prototyping */
void dn_nsp_send_data_ack(struct sock *sk);
void dn_nsp_send_oth_ack(struct sock *sk);
void dn_send_conn_ack(struct sock *sk);
void dn_send_conn_conf(struct sock *sk, gfp_t gfp);
void dn_nsp_send_disc(struct sock *sk, unsigned char type,
unsigned short reason, gfp_t gfp);
void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type,
unsigned short reason);
void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval);
void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
void dn_nsp_output(struct sock *sk);
int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb,
struct sk_buff_head *q, unsigned short acknum);
void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp,
int oob);
unsigned long dn_nsp_persist(struct sock *sk);
int dn_nsp_xmit_timeout(struct sock *sk);
int dn_nsp_rx(struct sk_buff *);
int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock,
long timeo, int *err);
#define NSP_REASON_OK 0 /* No error */
#define NSP_REASON_NR 1 /* No resources */
#define NSP_REASON_UN 2 /* Unrecognised node name */
#define NSP_REASON_SD 3 /* Node shutting down */
#define NSP_REASON_ID 4 /* Invalid destination end user */
#define NSP_REASON_ER 5 /* End user lacks resources */
#define NSP_REASON_OB 6 /* Object too busy */
#define NSP_REASON_US 7 /* Unspecified error */
#define NSP_REASON_TP 8 /* Third-Party abort */
#define NSP_REASON_EA 9 /* End user has aborted the link */
#define NSP_REASON_IF 10 /* Invalid node name format */
#define NSP_REASON_LS 11 /* Local node shutdown */
#define NSP_REASON_LL 32 /* Node lacks logical-link resources */
#define NSP_REASON_LE 33 /* End user lacks logical-link resources */
#define NSP_REASON_UR 34 /* Unacceptable RQSTRID or PASSWORD field */
#define NSP_REASON_UA 36 /* Unacceptable ACCOUNT field */
#define NSP_REASON_TM 38 /* End user timed out logical link */
#define NSP_REASON_NU 39 /* Node unreachable */
#define NSP_REASON_NL 41 /* No-link message */
#define NSP_REASON_DC 42 /* Disconnect confirm */
#define NSP_REASON_IO 43 /* Image data field overflow */
#define NSP_DISCINIT 0x38
#define NSP_DISCCONF 0x48
/*------------------------- NSP - messages ------------------------------*/
/* Data Messages */
/*---------------*/
/* Data Messages (data segment/interrupt/link service) */
struct nsp_data_seg_msg {
__u8 msgflg;
__le16 dstaddr;
__le16 srcaddr;
} __packed;
struct nsp_data_opt_msg {
__le16 acknum;
__le16 segnum;
__le16 lsflgs;
} __packed;
struct nsp_data_opt_msg1 {
__le16 acknum;
__le16 segnum;
} __packed;
/* Acknowledgment Message (data/other data) */
struct nsp_data_ack_msg {
__u8 msgflg;
__le16 dstaddr;
__le16 srcaddr;
__le16 acknum;
} __packed;
/* Connect Acknowledgment Message */
struct nsp_conn_ack_msg {
__u8 msgflg;
__le16 dstaddr;
} __packed;
/* Connect Initiate/Retransmit Initiate/Connect Confirm */
struct nsp_conn_init_msg {
__u8 msgflg;
#define NSP_CI 0x18 /* Connect Initiate */
#define NSP_RCI 0x68 /* Retrans. Conn Init */
__le16 dstaddr;
__le16 srcaddr;
__u8 services;
#define NSP_FC_NONE 0x00 /* Flow Control None */
#define NSP_FC_SRC 0x04 /* Seg Req. Count */
#define NSP_FC_SCMC 0x08 /* Sess. Control Mess */
#define NSP_FC_MASK 0x0c /* FC type mask */
__u8 info;
__le16 segsize;
} __packed;
/* Disconnect Initiate/Disconnect Confirm */
struct nsp_disconn_init_msg {
__u8 msgflg;
__le16 dstaddr;
__le16 srcaddr;
__le16 reason;
} __packed;
struct srcobj_fmt {
__u8 format;
__u8 task;
__le16 grpcode;
__le16 usrcode;
__u8 dlen;
} __packed;
/*
* A collection of functions for manipulating the sequence
* numbers used in NSP. Similar in operation to the functions
* of the same name in TCP.
*/
static __inline__ int dn_before(__u16 seq1, __u16 seq2)
{
seq1 &= 0x0fff;
seq2 &= 0x0fff;
return (int)((seq1 - seq2) & 0x0fff) > 2048;
}
static __inline__ int dn_after(__u16 seq1, __u16 seq2)
{
seq1 &= 0x0fff;
seq2 &= 0x0fff;
return (int)((seq2 - seq1) & 0x0fff) > 2048;
}
static __inline__ int dn_equal(__u16 seq1, __u16 seq2)
{
return ((seq1 ^ seq2) & 0x0fff) == 0;
}
static __inline__ int dn_before_or_equal(__u16 seq1, __u16 seq2)
{
return (dn_before(seq1, seq2) || dn_equal(seq1, seq2));
}
static __inline__ void seq_add(__u16 *seq, __u16 off)
{
(*seq) += off;
(*seq) &= 0x0fff;
}
static __inline__ int seq_next(__u16 seq1, __u16 seq2)
{
return dn_equal(seq1 + 1, seq2);
}
/*
* Can we delay the ack ?
*/
static __inline__ int sendack(__u16 seq)
{
return (int)((seq & 0x1000) ? 0 : 1);
}
/*
* Is socket congested ?
*/
static __inline__ int dn_congested(struct sock *sk)
{
return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
}
#define DN_MAX_NSP_DATA_HEADER (11)
#endif /* _NET_DN_NSP_H */
+123
View File
@@ -0,0 +1,123 @@
#ifndef _NET_DN_ROUTE_H
#define _NET_DN_ROUTE_H
/******************************************************************************
(c) 1995-1998 E.M. Serrat emserrat@geocities.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*******************************************************************************/
struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *,
struct sock *sk, int flags);
int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
void dn_rt_cache_flush(int delay);
int dn_route_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev);
/* Masks for flags field */
#define DN_RT_F_PID 0x07 /* Mask for packet type */
#define DN_RT_F_PF 0x80 /* Padding Follows */
#define DN_RT_F_VER 0x40 /* Version =0 discard packet if ==1 */
#define DN_RT_F_IE 0x20 /* Intra Ethernet, Reserved in short pkt */
#define DN_RT_F_RTS 0x10 /* Packet is being returned to sender */
#define DN_RT_F_RQR 0x08 /* Return packet to sender upon non-delivery */
/* Mask for types of routing packets */
#define DN_RT_PKT_MSK 0x06
/* Types of routing packets */
#define DN_RT_PKT_SHORT 0x02 /* Short routing packet */
#define DN_RT_PKT_LONG 0x06 /* Long routing packet */
/* Mask for control/routing selection */
#define DN_RT_PKT_CNTL 0x01 /* Set to 1 if a control packet */
/* Types of control packets */
#define DN_RT_CNTL_MSK 0x0f /* Mask for control packets */
#define DN_RT_PKT_INIT 0x01 /* Initialisation packet */
#define DN_RT_PKT_VERI 0x03 /* Verification Message */
#define DN_RT_PKT_HELO 0x05 /* Hello and Test Message */
#define DN_RT_PKT_L1RT 0x07 /* Level 1 Routing Message */
#define DN_RT_PKT_L2RT 0x09 /* Level 2 Routing Message */
#define DN_RT_PKT_ERTH 0x0b /* Ethernet Router Hello */
#define DN_RT_PKT_EEDH 0x0d /* Ethernet EndNode Hello */
/* Values for info field in hello message */
#define DN_RT_INFO_TYPE 0x03 /* Type mask */
#define DN_RT_INFO_L1RT 0x02 /* L1 Router */
#define DN_RT_INFO_L2RT 0x01 /* L2 Router */
#define DN_RT_INFO_ENDN 0x03 /* EndNode */
#define DN_RT_INFO_VERI 0x04 /* Verification Reqd. */
#define DN_RT_INFO_RJCT 0x08 /* Reject Flag, Reserved */
#define DN_RT_INFO_VFLD 0x10 /* Verification Failed, Reserved */
#define DN_RT_INFO_NOML 0x20 /* No Multicast traffic accepted */
#define DN_RT_INFO_BLKR 0x40 /* Blocking Requested */
/*
* The fl structure is what we used to look up the route.
* The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr
* except for local input routes, where the rt_saddr = fl.fld_dst and
* rt_daddr = fl.fld_src to allow the route to be used for returning
* packets to the originating host.
*/
struct dn_route {
struct dst_entry dst;
struct dn_route __rcu *dn_next;
struct neighbour *n;
struct flowidn fld;
__le16 rt_saddr;
__le16 rt_daddr;
__le16 rt_gateway;
__le16 rt_local_src; /* Source used for forwarding packets */
__le16 rt_src_map;
__le16 rt_dst_map;
unsigned int rt_flags;
unsigned int rt_type;
};
static inline bool dn_is_input_route(struct dn_route *rt)
{
return rt->fld.flowidn_iif != 0;
}
static inline bool dn_is_output_route(struct dn_route *rt)
{
return rt->fld.flowidn_iif == 0;
}
void dn_route_init(void);
void dn_route_cleanup(void);
#include <net/sock.h>
#include <linux/if_arp.h>
static inline void dn_rt_send(struct sk_buff *skb)
{
dev_queue_xmit(skb);
}
static inline void dn_rt_finish_output(struct sk_buff *skb, char *dst, char *src)
{
struct net_device *dev = skb->dev;
if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
dst = NULL;
if (dev_hard_header(skb, dev, ETH_P_DNA_RT, dst, src, skb->len) >= 0)
dn_rt_send(skb);
else
kfree_skb(skb);
}
#endif /* _NET_DN_ROUTE_H */
+628
View File
@@ -0,0 +1,628 @@
/*
* include/net/dsa.h - Driver for Distributed Switch Architecture switch chips
* Copyright (c) 2008-2009 Marvell Semiconductor
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __LINUX_NET_DSA_H
#define __LINUX_NET_DSA_H
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/ethtool.h>
#include <linux/net_tstamp.h>
#include <linux/phy.h>
#include <net/devlink.h>
#include <net/switchdev.h>
struct tc_action;
struct phy_device;
struct fixed_phy_status;
struct phylink_link_state;
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = 0,
DSA_TAG_PROTO_BRCM,
DSA_TAG_PROTO_BRCM_PREPEND,
DSA_TAG_PROTO_DSA,
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_KSZ,
DSA_TAG_PROTO_LAN9303,
DSA_TAG_PROTO_MTK,
DSA_TAG_PROTO_QCA,
DSA_TAG_PROTO_TRAILER,
DSA_TAG_LAST, /* MUST BE LAST */
};
#define DSA_MAX_SWITCHES 4
#define DSA_MAX_PORTS 12
#define DSA_RTABLE_NONE -1
struct dsa_chip_data {
/*
* How to access the switch configuration registers.
*/
struct device *host_dev;
int sw_addr;
/*
* Reference to network devices
*/
struct device *netdev[DSA_MAX_PORTS];
/* set to size of eeprom if supported by the switch */
int eeprom_len;
/* Device tree node pointer for this specific switch chip
* used during switch setup in case additional properties
* and resources needs to be used
*/
struct device_node *of_node;
/*
* The names of the switch's ports. Use "cpu" to
* designate the switch port that the cpu is connected to,
* "dsa" to indicate that this port is a DSA link to
* another switch, NULL to indicate the port is unused,
* or any other string to indicate this is a physical port.
*/
char *port_names[DSA_MAX_PORTS];
struct device_node *port_dn[DSA_MAX_PORTS];
/*
* An array of which element [a] indicates which port on this
* switch should be used to send packets to that are destined
* for switch a. Can be NULL if there is only one switch chip.
*/
s8 rtable[DSA_MAX_SWITCHES];
};
struct dsa_platform_data {
/*
* Reference to a Linux network interface that connects
* to the root switch chip of the tree.
*/
struct device *netdev;
struct net_device *of_netdev;
/*
* Info structs describing each of the switch chips
* connected via this network interface.
*/
int nr_chips;
struct dsa_chip_data *chip;
};
struct packet_type;
struct dsa_switch;
struct dsa_device_ops {
struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt);
int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
int *offset);
};
struct dsa_switch_tree {
struct list_head list;
/* Notifier chain for switch-wide events */
struct raw_notifier_head nh;
/* Tree identifier */
unsigned int index;
/* Number of switches attached to this tree */
struct kref refcount;
/* Has this tree been applied to the hardware? */
bool setup;
/*
* Configuration data for the platform device that owns
* this dsa switch tree instance.
*/
struct dsa_platform_data *pd;
/*
* The switch port to which the CPU is attached.
*/
struct dsa_port *cpu_dp;
/*
* Data for the individual switch chips.
*/
struct dsa_switch *ds[DSA_MAX_SWITCHES];
};
/* TC matchall action types, only mirroring for now */
enum dsa_port_mall_action_type {
DSA_PORT_MALL_MIRROR,
};
/* TC mirroring entry */
struct dsa_mall_mirror_tc_entry {
u8 to_local_port;
bool ingress;
};
/* TC matchall entry */
struct dsa_mall_tc_entry {
struct list_head list;
unsigned long cookie;
enum dsa_port_mall_action_type type;
union {
struct dsa_mall_mirror_tc_entry mirror;
};
};
struct dsa_port {
/* A CPU port is physically connected to a master device.
* A user port exposed to userspace has a slave device.
*/
union {
struct net_device *master;
struct net_device *slave;
};
/* CPU port tagging operations used by master or slave devices */
const struct dsa_device_ops *tag_ops;
/* Copies for faster access in master receive hot path */
struct dsa_switch_tree *dst;
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt);
enum {
DSA_PORT_TYPE_UNUSED = 0,
DSA_PORT_TYPE_CPU,
DSA_PORT_TYPE_DSA,
DSA_PORT_TYPE_USER,
} type;
struct dsa_switch *ds;
unsigned int index;
const char *name;
const struct dsa_port *cpu_dp;
const char *mac;
struct device_node *dn;
unsigned int ageing_time;
u8 stp_state;
struct net_device *bridge_dev;
struct devlink_port devlink_port;
struct phylink *pl;
/*
* Original copy of the master netdev ethtool_ops
*/
const struct ethtool_ops *orig_ethtool_ops;
};
struct dsa_switch {
struct device *dev;
/*
* Parent switch tree, and switch index.
*/
struct dsa_switch_tree *dst;
unsigned int index;
/* Listener for switch fabric events */
struct notifier_block nb;
/*
* Give the switch driver somewhere to hang its private data
* structure.
*/
void *priv;
/*
* Configuration data for this switch.
*/
struct dsa_chip_data *cd;
/*
* The switch operations.
*/
const struct dsa_switch_ops *ops;
/*
* An array of which element [a] indicates which port on this
* switch should be used to send packets to that are destined
* for switch a. Can be NULL if there is only one switch chip.
*/
s8 rtable[DSA_MAX_SWITCHES];
/*
* Slave mii_bus and devices for the individual ports.
*/
u32 phys_mii_mask;
struct mii_bus *slave_mii_bus;
/* Ageing Time limits in msecs */
unsigned int ageing_time_min;
unsigned int ageing_time_max;
/* devlink used to represent this switch device */
struct devlink *devlink;
/* Number of switch port queues */
unsigned int num_tx_queues;
unsigned long *bitmap;
unsigned long _bitmap;
/* Dynamically allocated ports, keep last */
size_t num_ports;
struct dsa_port ports[];
};
static inline const struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p)
{
return &ds->ports[p];
}
static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p)
{
return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED;
}
static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
{
return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_CPU;
}
static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
{
return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_DSA;
}
static inline bool dsa_is_user_port(struct dsa_switch *ds, int p)
{
return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_USER;
}
static inline u32 dsa_user_ports(struct dsa_switch *ds)
{
u32 mask = 0;
int p;
for (p = 0; p < ds->num_ports; p++)
if (dsa_is_user_port(ds, p))
mask |= BIT(p);
return mask;
}
/* Return the local port used to reach an arbitrary switch port */
static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
int port)
{
if (device == ds->index)
return port;
else
return ds->rtable[device];
}
/* Return the local port used to reach the dedicated CPU port */
static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port)
{
const struct dsa_port *dp = dsa_to_port(ds, port);
const struct dsa_port *cpu_dp = dp->cpu_dp;
if (!cpu_dp)
return port;
return dsa_towards_port(ds, cpu_dp->ds->index, cpu_dp->index);
}
typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
bool is_static, void *data);
struct dsa_switch_ops {
#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
/*
* Legacy probing.
*/
const char *(*probe)(struct device *dsa_dev,
struct device *host_dev, int sw_addr,
void **priv);
#endif
enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds,
int port);
int (*setup)(struct dsa_switch *ds);
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
/*
* Access to the switch's PHY registers.
*/
int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
int (*phy_write)(struct dsa_switch *ds, int port,
int regnum, u16 val);
/*
* Link state adjustment (called from libphy)
*/
void (*adjust_link)(struct dsa_switch *ds, int port,
struct phy_device *phydev);
void (*fixed_link_update)(struct dsa_switch *ds, int port,
struct fixed_phy_status *st);
/*
* PHYLINK integration
*/
void (*phylink_validate)(struct dsa_switch *ds, int port,
unsigned long *supported,
struct phylink_link_state *state);
int (*phylink_mac_link_state)(struct dsa_switch *ds, int port,
struct phylink_link_state *state);
void (*phylink_mac_config)(struct dsa_switch *ds, int port,
unsigned int mode,
const struct phylink_link_state *state);
void (*phylink_mac_an_restart)(struct dsa_switch *ds, int port);
void (*phylink_mac_link_down)(struct dsa_switch *ds, int port,
unsigned int mode,
phy_interface_t interface);
void (*phylink_mac_link_up)(struct dsa_switch *ds, int port,
unsigned int mode,
phy_interface_t interface,
struct phy_device *phydev);
void (*phylink_fixed_state)(struct dsa_switch *ds, int port,
struct phylink_link_state *state);
/*
* ethtool hardware statistics.
*/
void (*get_strings)(struct dsa_switch *ds, int port,
u32 stringset, uint8_t *data);
void (*get_ethtool_stats)(struct dsa_switch *ds,
int port, uint64_t *data);
int (*get_sset_count)(struct dsa_switch *ds, int port, int sset);
void (*get_ethtool_phy_stats)(struct dsa_switch *ds,
int port, uint64_t *data);
/*
* ethtool Wake-on-LAN
*/
void (*get_wol)(struct dsa_switch *ds, int port,
struct ethtool_wolinfo *w);
int (*set_wol)(struct dsa_switch *ds, int port,
struct ethtool_wolinfo *w);
/*
* ethtool timestamp info
*/
int (*get_ts_info)(struct dsa_switch *ds, int port,
struct ethtool_ts_info *ts);
/*
* Suspend and resume
*/
int (*suspend)(struct dsa_switch *ds);
int (*resume)(struct dsa_switch *ds);
/*
* Port enable/disable
*/
int (*port_enable)(struct dsa_switch *ds, int port,
struct phy_device *phy);
void (*port_disable)(struct dsa_switch *ds, int port,
struct phy_device *phy);
/*
* Port's MAC EEE settings
*/
int (*set_mac_eee)(struct dsa_switch *ds, int port,
struct ethtool_eee *e);
int (*get_mac_eee)(struct dsa_switch *ds, int port,
struct ethtool_eee *e);
/* EEPROM access */
int (*get_eeprom_len)(struct dsa_switch *ds);
int (*get_eeprom)(struct dsa_switch *ds,
struct ethtool_eeprom *eeprom, u8 *data);
int (*set_eeprom)(struct dsa_switch *ds,
struct ethtool_eeprom *eeprom, u8 *data);
/*
* Register access.
*/
int (*get_regs_len)(struct dsa_switch *ds, int port);
void (*get_regs)(struct dsa_switch *ds, int port,
struct ethtool_regs *regs, void *p);
/*
* Bridge integration
*/
int (*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs);
int (*port_bridge_join)(struct dsa_switch *ds, int port,
struct net_device *bridge);
void (*port_bridge_leave)(struct dsa_switch *ds, int port,
struct net_device *bridge);
void (*port_stp_state_set)(struct dsa_switch *ds, int port,
u8 state);
void (*port_fast_age)(struct dsa_switch *ds, int port);
/*
* VLAN support
*/
int (*port_vlan_filtering)(struct dsa_switch *ds, int port,
bool vlan_filtering);
int (*port_vlan_prepare)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
void (*port_vlan_add)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
int (*port_vlan_del)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
/*
* Forwarding database
*/
int (*port_fdb_add)(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid);
int (*port_fdb_del)(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid);
int (*port_fdb_dump)(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data);
/*
* Multicast database
*/
int (*port_mdb_prepare)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
void (*port_mdb_add)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
int (*port_mdb_del)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
/*
* RXNFC
*/
int (*get_rxnfc)(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc, u32 *rule_locs);
int (*set_rxnfc)(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc);
/*
* TC integration
*/
int (*port_mirror_add)(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror,
bool ingress);
void (*port_mirror_del)(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror);
/*
* Cross-chip operations
*/
int (*crosschip_bridge_join)(struct dsa_switch *ds, int sw_index,
int port, struct net_device *br);
void (*crosschip_bridge_leave)(struct dsa_switch *ds, int sw_index,
int port, struct net_device *br);
/*
* PTP functionality
*/
int (*port_hwtstamp_get)(struct dsa_switch *ds, int port,
struct ifreq *ifr);
int (*port_hwtstamp_set)(struct dsa_switch *ds, int port,
struct ifreq *ifr);
bool (*port_txtstamp)(struct dsa_switch *ds, int port,
struct sk_buff *clone, unsigned int type);
bool (*port_rxtstamp)(struct dsa_switch *ds, int port,
struct sk_buff *skb, unsigned int type);
};
struct dsa_switch_driver {
struct list_head list;
const struct dsa_switch_ops *ops;
};
#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
/* Legacy driver registration */
void register_switch_driver(struct dsa_switch_driver *type);
void unregister_switch_driver(struct dsa_switch_driver *type);
struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev);
#else
static inline void register_switch_driver(struct dsa_switch_driver *type) { }
static inline void unregister_switch_driver(struct dsa_switch_driver *type) { }
static inline struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev)
{
return NULL;
}
#endif
struct net_device *dsa_dev_to_net_device(struct device *dev);
/* Keep inline for faster access in hot path */
static inline bool netdev_uses_dsa(struct net_device *dev)
{
#if IS_ENABLED(CONFIG_NET_DSA)
return dev->dsa_ptr && dev->dsa_ptr->rcv;
#endif
return false;
}
struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n);
void dsa_unregister_switch(struct dsa_switch *ds);
int dsa_register_switch(struct dsa_switch *ds);
#ifdef CONFIG_PM_SLEEP
int dsa_switch_suspend(struct dsa_switch *ds);
int dsa_switch_resume(struct dsa_switch *ds);
#else
static inline int dsa_switch_suspend(struct dsa_switch *ds)
{
return 0;
}
static inline int dsa_switch_resume(struct dsa_switch *ds)
{
return 0;
}
#endif /* CONFIG_PM_SLEEP */
enum dsa_notifier_type {
DSA_PORT_REGISTER,
DSA_PORT_UNREGISTER,
};
struct dsa_notifier_info {
struct net_device *dev;
};
struct dsa_notifier_register_info {
struct dsa_notifier_info info; /* must be first */
struct net_device *master;
unsigned int port_number;
unsigned int switch_number;
};
static inline struct net_device *
dsa_notifier_info_to_dev(const struct dsa_notifier_info *info)
{
return info->dev;
}
#if IS_ENABLED(CONFIG_NET_DSA)
int register_dsa_notifier(struct notifier_block *nb);
int unregister_dsa_notifier(struct notifier_block *nb);
int call_dsa_notifiers(unsigned long val, struct net_device *dev,
struct dsa_notifier_info *info);
#else
static inline int register_dsa_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int unregister_dsa_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int call_dsa_notifiers(unsigned long val, struct net_device *dev,
struct dsa_notifier_info *info)
{
return NOTIFY_DONE;
}
#endif
/* Broadcom tag specific helpers to insert and extract queue/port number */
#define BRCM_TAG_SET_PORT_QUEUE(p, q) ((p) << 8 | q)
#define BRCM_TAG_GET_PORT(v) ((v) >> 8)
#define BRCM_TAG_GET_QUEUE(v) ((v) & 0xff)
int dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data);
int dsa_port_get_ethtool_phy_stats(struct dsa_port *dp, uint64_t *data);
int dsa_port_get_phy_sset_count(struct dsa_port *dp);
void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up);
#endif
+53
View File
@@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* include/net/dsfield.h - Manipulation of the Differentiated Services field */
/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
#ifndef __NET_DSFIELD_H
#define __NET_DSFIELD_H
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <asm/byteorder.h>
static inline __u8 ipv4_get_dsfield(const struct iphdr *iph)
{
return iph->tos;
}
static inline __u8 ipv6_get_dsfield(const struct ipv6hdr *ipv6h)
{
return ntohs(*(const __be16 *)ipv6h) >> 4;
}
static inline void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
__u8 value)
{
__u32 check = ntohs((__force __be16)iph->check);
__u8 dsfield;
dsfield = (iph->tos & mask) | value;
check += iph->tos;
if ((check+1) >> 16) check = (check+1) & 0xffff;
check -= dsfield;
check += check >> 16; /* adjust carry */
iph->check = (__force __sum16)htons(check);
iph->tos = dsfield;
}
static inline void ipv6_change_dsfield(struct ipv6hdr *ipv6h,__u8 mask,
__u8 value)
{
__be16 *p = (__force __be16 *)ipv6h;
*p = (*p & htons((((u16)mask << 4) | 0xf00f))) | htons((u16)value << 4);
}
#endif
+560
View File
@@ -0,0 +1,560 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* net/dst.h Protocol independent destination cache definitions.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
*/
#ifndef _NET_DST_H
#define _NET_DST_H
#include <net/dst_ops.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
#include <linux/bug.h>
#include <linux/jiffies.h>
#include <linux/refcount.h>
#include <net/neighbour.h>
#include <asm/processor.h>
#define DST_GC_MIN (HZ/10)
#define DST_GC_INC (HZ/2)
#define DST_GC_MAX (120*HZ)
/* Each dst_entry has reference count and sits in some parent list(s).
* When it is removed from parent list, it is "freed" (dst_free).
* After this it enters dead state (dst->obsolete > 0) and if its refcnt
* is zero, it can be destroyed immediately, otherwise it is added
* to gc list and garbage collector periodically checks the refcnt.
*/
struct sk_buff;
struct dst_entry {
struct net_device *dev;
struct dst_ops *ops;
unsigned long _metrics;
unsigned long expires;
#ifdef CONFIG_XFRM
struct xfrm_state *xfrm;
#else
void *__pad1;
#endif
int (*input)(struct sk_buff *);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
unsigned short flags;
#define DST_HOST 0x0001
#define DST_NOXFRM 0x0002
#define DST_NOPOLICY 0x0004
#define DST_NOCOUNT 0x0008
#define DST_FAKE_RTABLE 0x0010
#define DST_XFRM_TUNNEL 0x0020
#define DST_XFRM_QUEUE 0x0040
#define DST_METADATA 0x0080
/* A non-zero value of dst->obsolete forces by-hand validation
* of the route entry. Positive values are set by the generic
* dst layer to indicate that the entry has been forcefully
* destroyed.
*
* Negative values are used by the implementation layer code to
* force invocation of the dst_ops->check() method.
*/
short obsolete;
#define DST_OBSOLETE_NONE 0
#define DST_OBSOLETE_DEAD 2
#define DST_OBSOLETE_FORCE_CHK -1
#define DST_OBSOLETE_KILL -2
unsigned short header_len; /* more space at head required */
unsigned short trailer_len; /* space to reserve at tail */
/*
* __refcnt wants to be on a different cache line from
* input/output/ops or performance tanks badly
*/
#ifdef CONFIG_64BIT
atomic_t __refcnt; /* 64-bit offset 64 */
#endif
int __use;
unsigned long lastuse;
struct lwtunnel_state *lwtstate;
struct rcu_head rcu_head;
short error;
short __pad;
__u32 tclassid;
#ifndef CONFIG_64BIT
atomic_t __refcnt; /* 32-bit offset 64 */
#endif
};
struct dst_metrics {
u32 metrics[RTAX_MAX];
refcount_t refcnt;
} __aligned(4); /* Low pointer bits contain DST_METRICS_FLAGS */
extern const struct dst_metrics dst_default_metrics;
u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
#define DST_METRICS_READ_ONLY 0x1UL
#define DST_METRICS_REFCOUNTED 0x2UL
#define DST_METRICS_FLAGS 0x3UL
#define __DST_METRICS_PTR(Y) \
((u32 *)((Y) & ~DST_METRICS_FLAGS))
#define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics)
static inline bool dst_metrics_read_only(const struct dst_entry *dst)
{
return dst->_metrics & DST_METRICS_READ_ONLY;
}
void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old);
static inline void dst_destroy_metrics_generic(struct dst_entry *dst)
{
unsigned long val = dst->_metrics;
if (!(val & DST_METRICS_READ_ONLY))
__dst_destroy_metrics_generic(dst, val);
}
static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst)
{
unsigned long p = dst->_metrics;
BUG_ON(!p);
if (p & DST_METRICS_READ_ONLY)
return dst->ops->cow_metrics(dst, p);
return __DST_METRICS_PTR(p);
}
/* This may only be invoked before the entry has reached global
* visibility.
*/
static inline void dst_init_metrics(struct dst_entry *dst,
const u32 *src_metrics,
bool read_only)
{
dst->_metrics = ((unsigned long) src_metrics) |
(read_only ? DST_METRICS_READ_ONLY : 0);
}
static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
{
u32 *dst_metrics = dst_metrics_write_ptr(dest);
if (dst_metrics) {
u32 *src_metrics = DST_METRICS_PTR(src);
memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32));
}
}
static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
{
return DST_METRICS_PTR(dst);
}
static inline u32
dst_metric_raw(const struct dst_entry *dst, const int metric)
{
u32 *p = DST_METRICS_PTR(dst);
return p[metric-1];
}
static inline u32
dst_metric(const struct dst_entry *dst, const int metric)
{
WARN_ON_ONCE(metric == RTAX_HOPLIMIT ||
metric == RTAX_ADVMSS ||
metric == RTAX_MTU);
return dst_metric_raw(dst, metric);
}
static inline u32
dst_metric_advmss(const struct dst_entry *dst)
{
u32 advmss = dst_metric_raw(dst, RTAX_ADVMSS);
if (!advmss)
advmss = dst->ops->default_advmss(dst);
return advmss;
}
static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
{
u32 *p = dst_metrics_write_ptr(dst);
if (p)
p[metric-1] = val;
}
/* Kernel-internal feature bits that are unallocated in user space. */
#define DST_FEATURE_ECN_CA (1 << 31)
#define DST_FEATURE_MASK (DST_FEATURE_ECN_CA)
#define DST_FEATURE_ECN_MASK (DST_FEATURE_ECN_CA | RTAX_FEATURE_ECN)
static inline u32
dst_feature(const struct dst_entry *dst, u32 feature)
{
return dst_metric(dst, RTAX_FEATURES) & feature;
}
static inline u32 dst_mtu(const struct dst_entry *dst)
{
return dst->ops->mtu(dst);
}
/* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric)
{
return msecs_to_jiffies(dst_metric(dst, metric));
}
static inline u32
dst_allfrag(const struct dst_entry *dst)
{
int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG);
return ret;
}
static inline int
dst_metric_locked(const struct dst_entry *dst, int metric)
{
return dst_metric(dst, RTAX_LOCK) & (1<<metric);
}
static inline void dst_hold(struct dst_entry *dst)
{
/*
* If your kernel compilation stops here, please check
* the placement of __refcnt in struct dst_entry
*/
BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63);
WARN_ON(atomic_inc_not_zero(&dst->__refcnt) == 0);
}
static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
{
if (unlikely(time != dst->lastuse)) {
dst->__use++;
dst->lastuse = time;
}
}
static inline void dst_hold_and_use(struct dst_entry *dst, unsigned long time)
{
dst_hold(dst);
dst_use_noref(dst, time);
}
static inline struct dst_entry *dst_clone(struct dst_entry *dst)
{
if (dst)
dst_hold(dst);
return dst;
}
void dst_release(struct dst_entry *dst);
void dst_release_immediate(struct dst_entry *dst);
static inline void refdst_drop(unsigned long refdst)
{
if (!(refdst & SKB_DST_NOREF))
dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK));
}
/**
* skb_dst_drop - drops skb dst
* @skb: buffer
*
* Drops dst reference count if a reference was taken.
*/
static inline void skb_dst_drop(struct sk_buff *skb)
{
if (skb->_skb_refdst) {
refdst_drop(skb->_skb_refdst);
skb->_skb_refdst = 0UL;
}
}
static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst)
{
nskb->_skb_refdst = refdst;
if (!(nskb->_skb_refdst & SKB_DST_NOREF))
dst_clone(skb_dst(nskb));
}
static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb)
{
__skb_dst_copy(nskb, oskb->_skb_refdst);
}
/**
* dst_hold_safe - Take a reference on a dst if possible
* @dst: pointer to dst entry
*
* This helper returns false if it could not safely
* take a reference on a dst.
*/
static inline bool dst_hold_safe(struct dst_entry *dst)
{
return atomic_inc_not_zero(&dst->__refcnt);
}
/**
* skb_dst_force - makes sure skb dst is refcounted
* @skb: buffer
*
* If dst is not yet refcounted and not destroyed, grab a ref on it.
* Returns true if dst is refcounted.
*/
static inline bool skb_dst_force(struct sk_buff *skb)
{
if (skb_dst_is_noref(skb)) {
struct dst_entry *dst = skb_dst(skb);
WARN_ON(!rcu_read_lock_held());
if (!dst_hold_safe(dst))
dst = NULL;
skb->_skb_refdst = (unsigned long)dst;
}
return skb->_skb_refdst != 0UL;
}
/**
* __skb_tunnel_rx - prepare skb for rx reinsert
* @skb: buffer
* @dev: tunnel device
* @net: netns for packet i/o
*
* After decapsulation, packet is going to re-enter (netif_rx()) our stack,
* so make some cleanups. (no accounting done)
*/
static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
struct net *net)
{
skb->dev = dev;
/*
* Clear hash so that we can recalulate the hash for the
* encapsulated packet, unless we have already determine the hash
* over the L4 4-tuple.
*/
skb_clear_hash_if_not_l4(skb);
skb_set_queue_mapping(skb, 0);
skb_scrub_packet(skb, !net_eq(net, dev_net(dev)));
}
/**
* skb_tunnel_rx - prepare skb for rx reinsert
* @skb: buffer
* @dev: tunnel device
* @net: netns for packet i/o
*
* After decapsulation, packet is going to re-enter (netif_rx()) our stack,
* so make some cleanups, and perform accounting.
* Note: this accounting is not SMP safe.
*/
static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
struct net *net)
{
/* TODO : stats should be SMP safe */
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
__skb_tunnel_rx(skb, dev, net);
}
static inline u32 dst_tclassid(const struct sk_buff *skb)
{
#ifdef CONFIG_IP_ROUTE_CLASSID
const struct dst_entry *dst;
dst = skb_dst(skb);
if (dst)
return dst->tclassid;
#endif
return 0;
}
int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
static inline int dst_discard(struct sk_buff *skb)
{
return dst_discard_out(&init_net, skb->sk, skb);
}
void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref,
int initial_obsolete, unsigned short flags);
void dst_init(struct dst_entry *dst, struct dst_ops *ops,
struct net_device *dev, int initial_ref, int initial_obsolete,
unsigned short flags);
struct dst_entry *dst_destroy(struct dst_entry *dst);
void dst_dev_put(struct dst_entry *dst);
static inline void dst_confirm(struct dst_entry *dst)
{
}
static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
struct neighbour *n = dst->ops->neigh_lookup(dst, NULL, daddr);
return IS_ERR(n) ? NULL : n;
}
static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
struct sk_buff *skb)
{
struct neighbour *n = NULL;
/* The packets from tunnel devices (eg bareudp) may have only
* metadata in the dst pointer of skb. Hence a pointer check of
* neigh_lookup is needed.
*/
if (dst->ops->neigh_lookup)
n = dst->ops->neigh_lookup(dst, skb, NULL);
return IS_ERR(n) ? NULL : n;
}
static inline void dst_confirm_neigh(const struct dst_entry *dst,
const void *daddr)
{
if (dst->ops->confirm_neigh)
dst->ops->confirm_neigh(dst, daddr);
}
static inline void dst_link_failure(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
if (dst && dst->ops && dst->ops->link_failure)
dst->ops->link_failure(skb);
}
static inline void dst_set_expires(struct dst_entry *dst, int timeout)
{
unsigned long expires = jiffies + timeout;
if (expires == 0)
expires = 1;
if (dst->expires == 0 || time_before(expires, dst->expires))
dst->expires = expires;
}
/* Output packet to network from transport. */
static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return skb_dst(skb)->output(net, sk, skb);
}
/* Input packet from network to transport. */
static inline int dst_input(struct sk_buff *skb)
{
return skb_dst(skb)->input(skb);
}
static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
{
if (dst->obsolete)
dst = dst->ops->check(dst, cookie);
return dst;
}
/* Flags for xfrm_lookup flags argument. */
enum {
XFRM_LOOKUP_ICMP = 1 << 0,
XFRM_LOOKUP_QUEUE = 1 << 1,
XFRM_LOOKUP_KEEP_DST_REF = 1 << 2,
};
struct flowi;
#ifndef CONFIG_XFRM
static inline struct dst_entry *xfrm_lookup(struct net *net,
struct dst_entry *dst_orig,
const struct flowi *fl,
const struct sock *sk,
int flags)
{
return dst_orig;
}
static inline struct dst_entry *
xfrm_lookup_with_ifid(struct net *net, struct dst_entry *dst_orig,
const struct flowi *fl, const struct sock *sk,
int flags, u32 if_id)
{
return dst_orig;
}
static inline struct dst_entry *xfrm_lookup_route(struct net *net,
struct dst_entry *dst_orig,
const struct flowi *fl,
const struct sock *sk,
int flags)
{
return dst_orig;
}
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
{
return NULL;
}
#else
struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
const struct flowi *fl, const struct sock *sk,
int flags);
struct dst_entry *xfrm_lookup_with_ifid(struct net *net,
struct dst_entry *dst_orig,
const struct flowi *fl,
const struct sock *sk, int flags,
u32 if_id);
struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
const struct flowi *fl, const struct sock *sk,
int flags);
/* skb attached with this dst needs transformation if dst->xfrm is valid */
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
{
return dst->xfrm;
}
#endif
static inline void skb_dst_update_pmtu(struct sk_buff *skb, u32 mtu)
{
struct dst_entry *dst = skb_dst(skb);
if (dst && dst->ops->update_pmtu)
dst->ops->update_pmtu(dst, NULL, skb, mtu, true);
}
/* update dst pmtu but not do neighbor confirm */
static inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu)
{
struct dst_entry *dst = skb_dst(skb);
if (dst && dst->ops->update_pmtu)
dst->ops->update_pmtu(dst, NULL, skb, mtu, false);
}
static inline void skb_tunnel_check_pmtu(struct sk_buff *skb,
struct dst_entry *encap_dst,
int headroom)
{
u32 encap_mtu = dst_mtu(encap_dst);
if (skb->len > encap_mtu - headroom)
skb_dst_update_pmtu_no_confirm(skb, encap_mtu - headroom);
}
#endif /* _NET_DST_H */
+98
View File
@@ -0,0 +1,98 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_DST_CACHE_H
#define _NET_DST_CACHE_H
#include <linux/jiffies.h>
#include <net/dst.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ip6_fib.h>
#endif
struct dst_cache {
struct dst_cache_pcpu __percpu *cache;
unsigned long reset_ts;
};
/**
* dst_cache_get - perform cache lookup
* @dst_cache: the cache
*
* The caller should use dst_cache_get_ip4() if it need to retrieve the
* source address to be used when xmitting to the cached dst.
* local BH must be disabled.
*/
struct dst_entry *dst_cache_get(struct dst_cache *dst_cache);
/**
* dst_cache_get_ip4 - perform cache lookup and fetch ipv4 source address
* @dst_cache: the cache
* @saddr: return value for the retrieved source address
*
* local BH must be disabled.
*/
struct rtable *dst_cache_get_ip4(struct dst_cache *dst_cache, __be32 *saddr);
/**
* dst_cache_set_ip4 - store the ipv4 dst into the cache
* @dst_cache: the cache
* @dst: the entry to be cached
* @saddr: the source address to be stored inside the cache
*
* local BH must be disabled.
*/
void dst_cache_set_ip4(struct dst_cache *dst_cache, struct dst_entry *dst,
__be32 saddr);
#if IS_ENABLED(CONFIG_IPV6)
/**
* dst_cache_set_ip6 - store the ipv6 dst into the cache
* @dst_cache: the cache
* @dst: the entry to be cached
* @saddr: the source address to be stored inside the cache
*
* local BH must be disabled.
*/
void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst,
const struct in6_addr *saddr);
/**
* dst_cache_get_ip6 - perform cache lookup and fetch ipv6 source address
* @dst_cache: the cache
* @saddr: return value for the retrieved source address
*
* local BH must be disabled.
*/
struct dst_entry *dst_cache_get_ip6(struct dst_cache *dst_cache,
struct in6_addr *saddr);
#endif
/**
* dst_cache_reset - invalidate the cache contents
* @dst_cache: the cache
*
* This does not free the cached dst to avoid races and contentions.
* the dst will be freed on later cache lookup.
*/
static inline void dst_cache_reset(struct dst_cache *dst_cache)
{
dst_cache->reset_ts = jiffies;
}
/**
* dst_cache_init - initialize the cache, allocating the required storage
* @dst_cache: the cache
* @gfp: allocation flags
*/
int dst_cache_init(struct dst_cache *dst_cache, gfp_t gfp);
/**
* dst_cache_destroy - empty the cache and free the allocated storage
* @dst_cache: the cache
*
* No synchronization is enforced: it must be called only when the cache
* is unsed.
*/
void dst_cache_destroy(struct dst_cache *dst_cache);
#endif
+217
View File
@@ -0,0 +1,217 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_DST_METADATA_H
#define __NET_DST_METADATA_H 1
#include <linux/skbuff.h>
#include <net/ip_tunnels.h>
#include <net/dst.h>
enum metadata_type {
METADATA_IP_TUNNEL,
METADATA_HW_PORT_MUX,
};
struct hw_port_info {
struct net_device *lower_dev;
u32 port_id;
};
struct metadata_dst {
struct dst_entry dst;
enum metadata_type type;
union {
struct ip_tunnel_info tun_info;
struct hw_port_info port_info;
} u;
};
static inline struct metadata_dst *skb_metadata_dst(const struct sk_buff *skb)
{
struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb);
if (md_dst && md_dst->dst.flags & DST_METADATA)
return md_dst;
return NULL;
}
static inline struct ip_tunnel_info *
skb_tunnel_info(const struct sk_buff *skb)
{
struct metadata_dst *md_dst = skb_metadata_dst(skb);
struct dst_entry *dst;
if (md_dst && md_dst->type == METADATA_IP_TUNNEL)
return &md_dst->u.tun_info;
dst = skb_dst(skb);
if (dst && dst->lwtstate)
return lwt_tun_info(dst->lwtstate);
return NULL;
}
static inline bool skb_valid_dst(const struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
return dst && !(dst->flags & DST_METADATA);
}
static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
const struct sk_buff *skb_b)
{
const struct metadata_dst *a, *b;
if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
return 0;
a = (const struct metadata_dst *) skb_dst(skb_a);
b = (const struct metadata_dst *) skb_dst(skb_b);
if (!a != !b || a->type != b->type)
return 1;
switch (a->type) {
case METADATA_HW_PORT_MUX:
return memcmp(&a->u.port_info, &b->u.port_info,
sizeof(a->u.port_info));
case METADATA_IP_TUNNEL:
return memcmp(&a->u.tun_info, &b->u.tun_info,
sizeof(a->u.tun_info) +
a->u.tun_info.options_len);
default:
return 1;
}
}
void metadata_dst_free(struct metadata_dst *);
struct metadata_dst *metadata_dst_alloc(u8 optslen, enum metadata_type type,
gfp_t flags);
void metadata_dst_free_percpu(struct metadata_dst __percpu *md_dst);
struct metadata_dst __percpu *
metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags);
static inline struct metadata_dst *tun_rx_dst(int md_size)
{
struct metadata_dst *tun_dst;
tun_dst = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
if (!tun_dst)
return NULL;
tun_dst->u.tun_info.options_len = 0;
tun_dst->u.tun_info.mode = 0;
return tun_dst;
}
static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
{
struct metadata_dst *md_dst = skb_metadata_dst(skb);
int md_size;
struct metadata_dst *new_md;
if (!md_dst || md_dst->type != METADATA_IP_TUNNEL)
return ERR_PTR(-EINVAL);
md_size = md_dst->u.tun_info.options_len;
new_md = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
if (!new_md)
return ERR_PTR(-ENOMEM);
memcpy(&new_md->u.tun_info, &md_dst->u.tun_info,
sizeof(struct ip_tunnel_info) + md_size);
skb_dst_drop(skb);
dst_hold(&new_md->dst);
skb_dst_set(skb, &new_md->dst);
return new_md;
}
static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb)
{
struct metadata_dst *dst;
dst = tun_dst_unclone(skb);
if (IS_ERR(dst))
return NULL;
return &dst->u.tun_info;
}
static inline struct metadata_dst *__ip_tun_set_dst(__be32 saddr,
__be32 daddr,
__u8 tos, __u8 ttl,
__be16 tp_dst,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
struct metadata_dst *tun_dst;
tun_dst = tun_rx_dst(md_size);
if (!tun_dst)
return NULL;
ip_tunnel_key_init(&tun_dst->u.tun_info.key,
saddr, daddr, tos, ttl,
0, 0, tp_dst, tunnel_id, flags);
return tun_dst;
}
static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
const struct iphdr *iph = ip_hdr(skb);
return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
0, flags, tunnel_id, md_size);
}
static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr,
const struct in6_addr *daddr,
__u8 tos, __u8 ttl,
__be16 tp_dst,
__be32 label,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
struct metadata_dst *tun_dst;
struct ip_tunnel_info *info;
tun_dst = tun_rx_dst(md_size);
if (!tun_dst)
return NULL;
info = &tun_dst->u.tun_info;
info->mode = IP_TUNNEL_INFO_IPV6;
info->key.tun_flags = flags;
info->key.tun_id = tunnel_id;
info->key.tp_src = 0;
info->key.tp_dst = tp_dst;
info->key.u.ipv6.src = *saddr;
info->key.u.ipv6.dst = *daddr;
info->key.tos = tos;
info->key.ttl = ttl;
info->key.label = label;
return tun_dst;
}
static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
__be16 flags,
__be64 tunnel_id,
int md_size)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
return __ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr,
ipv6_get_dsfield(ip6h), ip6h->hop_limit,
0, ip6_flowlabel(ip6h), flags, tunnel_id,
md_size);
}
#endif /* __NET_DST_METADATA_H */
+81
View File
@@ -0,0 +1,81 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_DST_OPS_H
#define _NET_DST_OPS_H
#include <linux/types.h>
#include <linux/percpu_counter.h>
#include <linux/cache.h>
struct dst_entry;
struct kmem_cachep;
struct net_device;
struct sk_buff;
struct sock;
struct net;
/* *** ANDROID FIXUP ***
* These typedefs are used to help fixup the ABI break caused by commit
* 92f1655aa2b2 ("net: fix __dst_negative_advice() race") where the
* negative_advice callback changed function signatures.
* See b/343727534 for more details.
* *** ANDROID FIXUP ***
*/
typedef void (*android_dst_ops_negative_advice_new_t)(struct sock *sk, struct dst_entry *);
typedef struct dst_entry * (*android_dst_ops_negative_advice_old_t)(struct dst_entry *);
struct dst_ops {
unsigned short family;
unsigned int gc_thresh;
int (*gc)(struct dst_ops *ops);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
unsigned int (*default_advmss)(const struct dst_entry *);
unsigned int (*mtu)(const struct dst_entry *);
u32 * (*cow_metrics)(struct dst_entry *, unsigned long);
void (*destroy)(struct dst_entry *);
void (*ifdown)(struct dst_entry *,
struct net_device *dev, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu,
bool confirm_neigh);
void (*redirect)(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb);
int (*local_out)(struct net *net, struct sock *sk, struct sk_buff *skb);
struct neighbour * (*neigh_lookup)(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr);
void (*confirm_neigh)(const struct dst_entry *dst,
const void *daddr);
struct kmem_cache *kmem_cachep;
struct percpu_counter pcpuc_entries ____cacheline_aligned_in_smp;
};
static inline int dst_entries_get_fast(struct dst_ops *dst)
{
return percpu_counter_read_positive(&dst->pcpuc_entries);
}
static inline int dst_entries_get_slow(struct dst_ops *dst)
{
return percpu_counter_sum_positive(&dst->pcpuc_entries);
}
static inline void dst_entries_add(struct dst_ops *dst, int val)
{
percpu_counter_add(&dst->pcpuc_entries, val);
}
static inline int dst_entries_init(struct dst_ops *dst)
{
return percpu_counter_init(&dst->pcpuc_entries, 0, GFP_KERNEL);
}
static inline void dst_entries_destroy(struct dst_ops *dst)
{
percpu_counter_destroy(&dst->pcpuc_entries);
}
#endif
+303
View File
@@ -0,0 +1,303 @@
#ifndef __LINUX_ERSPAN_H
#define __LINUX_ERSPAN_H
/*
* GRE header for ERSPAN encapsulation (8 octets [34:41]) -- 8 bytes
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |0|0|0|1|0|00000|000000000|00000| Protocol Type for ERSPAN |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number (increments per packet per session) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Note that in the above GRE header [RFC1701] out of the C, R, K, S,
* s, Recur, Flags, Version fields only S (bit 03) is set to 1. The
* other fields are set to zero, so only a sequence number follows.
*
* ERSPAN Version 1 (Type II) header (8 octets [42:49])
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Ver | VLAN | COS | En|T| Session ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Reserved | Index |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
* ERSPAN Version 2 (Type III) header (12 octets [42:49])
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Ver | VLAN | COS |BSO|T| Session ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Timestamp |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SGT |P| FT | Hw ID |D|Gra|O|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Platform Specific SubHeader (8 octets, optional)
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Platf ID | Platform Specific Info |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Platform Specific Info |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB
*/
#include <uapi/linux/erspan.h>
#define ERSPAN_VERSION 0x1 /* ERSPAN type II */
#define VER_MASK 0xf000
#define VLAN_MASK 0x0fff
#define COS_MASK 0xe000
#define EN_MASK 0x1800
#define T_MASK 0x0400
#define ID_MASK 0x03ff
#define INDEX_MASK 0xfffff
#define ERSPAN_VERSION2 0x2 /* ERSPAN type III*/
#define BSO_MASK EN_MASK
#define SGT_MASK 0xffff0000
#define P_MASK 0x8000
#define FT_MASK 0x7c00
#define HWID_MASK 0x03f0
#define DIR_MASK 0x0008
#define GRA_MASK 0x0006
#define O_MASK 0x0001
#define HWID_OFFSET 4
#define DIR_OFFSET 3
enum erspan_encap_type {
ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */
ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */
ERSPAN_ENCAP_8021Q = 0x2, /* originally 802.1Q encapsulated */
ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */
};
#define ERSPAN_V1_MDSIZE 4
#define ERSPAN_V2_MDSIZE 8
struct erspan_base_hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 vlan_upper:4,
ver:4;
__u8 vlan:8;
__u8 session_id_upper:2,
t:1,
en:2,
cos:3;
__u8 session_id:8;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 ver: 4,
vlan_upper:4;
__u8 vlan:8;
__u8 cos:3,
en:2,
t:1,
session_id_upper:2;
__u8 session_id:8;
#else
#error "Please fix <asm/byteorder.h>"
#endif
};
static inline void set_session_id(struct erspan_base_hdr *ershdr, u16 id)
{
ershdr->session_id = id & 0xff;
ershdr->session_id_upper = (id >> 8) & 0x3;
}
static inline u16 get_session_id(const struct erspan_base_hdr *ershdr)
{
return (ershdr->session_id_upper << 8) + ershdr->session_id;
}
static inline void set_vlan(struct erspan_base_hdr *ershdr, u16 vlan)
{
ershdr->vlan = vlan & 0xff;
ershdr->vlan_upper = (vlan >> 8) & 0xf;
}
static inline u16 get_vlan(const struct erspan_base_hdr *ershdr)
{
return (ershdr->vlan_upper << 8) + ershdr->vlan;
}
static inline void set_hwid(struct erspan_md2 *md2, u8 hwid)
{
md2->hwid = hwid & 0xf;
md2->hwid_upper = (hwid >> 4) & 0x3;
}
static inline u8 get_hwid(const struct erspan_md2 *md2)
{
return (md2->hwid_upper << 4) + md2->hwid;
}
static inline int erspan_hdr_len(int version)
{
return sizeof(struct erspan_base_hdr) +
(version == 1 ? ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE);
}
static inline u8 tos_to_cos(u8 tos)
{
u8 dscp, cos;
dscp = tos >> 2;
cos = dscp >> 3;
return cos;
}
static inline void erspan_build_header(struct sk_buff *skb,
u32 id, u32 index,
bool truncate, bool is_ipv4)
{
struct ethhdr *eth = (struct ethhdr *)skb->data;
enum erspan_encap_type enc_type;
struct erspan_base_hdr *ershdr;
struct qtag_prefix {
__be16 eth_type;
__be16 tci;
} *qp;
u16 vlan_tci = 0;
u8 tos;
__be32 *idx;
tos = is_ipv4 ? ip_hdr(skb)->tos :
(ipv6_hdr(skb)->priority << 4) +
(ipv6_hdr(skb)->flow_lbl[0] >> 4);
enc_type = ERSPAN_ENCAP_NOVLAN;
/* If mirrored packet has vlan tag, extract tci and
* perserve vlan header in the mirrored frame.
*/
if (eth->h_proto == htons(ETH_P_8021Q)) {
qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
vlan_tci = ntohs(qp->tci);
enc_type = ERSPAN_ENCAP_INFRAME;
}
skb_push(skb, sizeof(*ershdr) + ERSPAN_V1_MDSIZE);
ershdr = (struct erspan_base_hdr *)skb->data;
memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE);
/* Build base header */
ershdr->ver = ERSPAN_VERSION;
ershdr->cos = tos_to_cos(tos);
ershdr->en = enc_type;
ershdr->t = truncate;
set_vlan(ershdr, vlan_tci);
set_session_id(ershdr, id);
/* Build metadata */
idx = (__be32 *)(ershdr + 1);
*idx = htonl(index & INDEX_MASK);
}
/* ERSPAN GRA: timestamp granularity
* 00b --> granularity = 100 microseconds
* 01b --> granularity = 100 nanoseconds
* 10b --> granularity = IEEE 1588
* Here we only support 100 microseconds.
*/
static inline __be32 erspan_get_timestamp(void)
{
u64 h_usecs;
ktime_t kt;
kt = ktime_get_real();
h_usecs = ktime_divns(kt, 100 * NSEC_PER_USEC);
/* ERSPAN base header only has 32-bit,
* so it wraps around 4 days.
*/
return htonl((u32)h_usecs);
}
/* ERSPAN BSO (Bad/Short/Oversized), see RFC1757
* 00b --> Good frame with no error, or unknown integrity
* 01b --> Payload is a Short Frame
* 10b --> Payload is an Oversized Frame
* 11b --> Payload is a Bad Frame with CRC or Alignment Error
*/
enum erspan_bso {
BSO_NOERROR = 0x0,
BSO_SHORT = 0x1,
BSO_OVERSIZED = 0x2,
BSO_BAD = 0x3,
};
static inline u8 erspan_detect_bso(struct sk_buff *skb)
{
/* BSO_BAD is not handled because the frame CRC
* or alignment error information is in FCS.
*/
if (skb->len < ETH_ZLEN)
return BSO_SHORT;
if (skb->len > ETH_FRAME_LEN)
return BSO_OVERSIZED;
return BSO_NOERROR;
}
static inline void erspan_build_header_v2(struct sk_buff *skb,
u32 id, u8 direction, u16 hwid,
bool truncate, bool is_ipv4)
{
struct ethhdr *eth = (struct ethhdr *)skb->data;
struct erspan_base_hdr *ershdr;
struct erspan_md2 *md2;
struct qtag_prefix {
__be16 eth_type;
__be16 tci;
} *qp;
u16 vlan_tci = 0;
u8 gra = 0; /* 100 usec */
u8 bso = 0; /* Bad/Short/Oversized */
u8 sgt = 0;
u8 tos;
tos = is_ipv4 ? ip_hdr(skb)->tos :
(ipv6_hdr(skb)->priority << 4) +
(ipv6_hdr(skb)->flow_lbl[0] >> 4);
/* Unlike v1, v2 does not have En field,
* so only extract vlan tci field.
*/
if (eth->h_proto == htons(ETH_P_8021Q)) {
qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
vlan_tci = ntohs(qp->tci);
}
bso = erspan_detect_bso(skb);
skb_push(skb, sizeof(*ershdr) + ERSPAN_V2_MDSIZE);
ershdr = (struct erspan_base_hdr *)skb->data;
memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE);
/* Build base header */
ershdr->ver = ERSPAN_VERSION2;
ershdr->cos = tos_to_cos(tos);
ershdr->en = bso;
ershdr->t = truncate;
set_vlan(ershdr, vlan_tci);
set_session_id(ershdr, id);
/* Build metadata */
md2 = (struct erspan_md2 *)(ershdr + 1);
md2->timestamp = erspan_get_timestamp();
md2->sgt = htons(sgt);
md2->p = 1;
md2->ft = 0;
md2->dir = direction;
md2->gra = gra;
md2->o = 0;
set_hwid(md2, hwid);
}
#endif
+33
View File
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_ESP_H
#define _NET_ESP_H
#include <linux/skbuff.h>
struct ip_esp_hdr;
static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
{
return (struct ip_esp_hdr *)skb_transport_header(skb);
}
struct esp_info {
struct ip_esp_hdr *esph;
__be64 seqno;
int tfclen;
int tailen;
int plen;
int clen;
int len;
int nfrags;
__u8 proto;
bool inplace;
};
int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp_input_done2(struct sk_buff *skb, int err);
int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp6_input_done2(struct sk_buff *skb, int err);
#endif
+23
View File
@@ -0,0 +1,23 @@
/*
* linux/include/net/ethoc.h
*
* Copyright (C) 2008-2009 Avionic Design GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Written by Thierry Reding <thierry.reding@avionic-design.de>
*/
#ifndef LINUX_NET_ETHOC_H
#define LINUX_NET_ETHOC_H 1
struct ethoc_platform_data {
u8 hwaddr[IFHWADDRLEN];
s8 phy_id;
u32 eth_clkfreq;
bool big_endian;
};
#endif /* !LINUX_NET_ETHOC_H */
+36
View File
@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018, Intel Corporation. */
#ifndef _FAILOVER_H
#define _FAILOVER_H
#include <linux/netdevice.h>
struct failover_ops {
int (*slave_pre_register)(struct net_device *slave_dev,
struct net_device *failover_dev);
int (*slave_register)(struct net_device *slave_dev,
struct net_device *failover_dev);
int (*slave_pre_unregister)(struct net_device *slave_dev,
struct net_device *failover_dev);
int (*slave_unregister)(struct net_device *slave_dev,
struct net_device *failover_dev);
int (*slave_link_change)(struct net_device *slave_dev,
struct net_device *failover_dev);
int (*slave_name_change)(struct net_device *slave_dev,
struct net_device *failover_dev);
rx_handler_result_t (*slave_handle_frame)(struct sk_buff **pskb);
};
struct failover {
struct list_head list;
struct net_device __rcu *failover_dev;
struct failover_ops __rcu *ops;
};
struct failover *failover_register(struct net_device *dev,
struct failover_ops *ops);
void failover_unregister(struct failover *failover);
int failover_slave_unregister(struct net_device *slave_dev);
#endif /* _FAILOVER_H */
+49
View File
@@ -0,0 +1,49 @@
#ifndef __NET_FIB_NOTIFIER_H
#define __NET_FIB_NOTIFIER_H
#include <linux/types.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <net/net_namespace.h>
struct fib_notifier_info {
struct net *net;
int family;
struct netlink_ext_ack *extack;
};
enum fib_event_type {
FIB_EVENT_ENTRY_REPLACE,
FIB_EVENT_ENTRY_APPEND,
FIB_EVENT_ENTRY_ADD,
FIB_EVENT_ENTRY_DEL,
FIB_EVENT_RULE_ADD,
FIB_EVENT_RULE_DEL,
FIB_EVENT_NH_ADD,
FIB_EVENT_NH_DEL,
FIB_EVENT_VIF_ADD,
FIB_EVENT_VIF_DEL,
};
struct fib_notifier_ops {
int family;
struct list_head list;
unsigned int (*fib_seq_read)(struct net *net);
int (*fib_dump)(struct net *net, struct notifier_block *nb);
struct module *owner;
struct rcu_head rcu;
};
int call_fib_notifier(struct notifier_block *nb, struct net *net,
enum fib_event_type event_type,
struct fib_notifier_info *info);
int call_fib_notifiers(struct net *net, enum fib_event_type event_type,
struct fib_notifier_info *info);
int register_fib_notifier(struct notifier_block *nb,
void (*cb)(struct notifier_block *nb));
int unregister_fib_notifier(struct notifier_block *nb);
struct fib_notifier_ops *
fib_notifier_ops_register(const struct fib_notifier_ops *tmpl, struct net *net);
void fib_notifier_ops_unregister(struct fib_notifier_ops *ops);
#endif
+204
View File
@@ -0,0 +1,204 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_FIB_RULES_H
#define __NET_FIB_RULES_H
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/fib_rules.h>
#include <linux/refcount.h>
#include <net/flow.h>
#include <net/rtnetlink.h>
#include <net/fib_notifier.h>
struct fib_kuid_range {
kuid_t start;
kuid_t end;
};
struct fib_rule {
struct list_head list;
int iifindex;
int oifindex;
u32 mark;
u32 mark_mask;
u32 flags;
u32 table;
u8 action;
u8 l3mdev;
u8 proto;
u8 ip_proto;
u32 target;
__be64 tun_id;
struct fib_rule __rcu *ctarget;
struct net *fr_net;
refcount_t refcnt;
u32 pref;
int suppress_ifgroup;
int suppress_prefixlen;
char iifname[IFNAMSIZ];
char oifname[IFNAMSIZ];
struct fib_kuid_range uid_range;
struct fib_rule_port_range sport_range;
struct fib_rule_port_range dport_range;
struct rcu_head rcu;
};
struct fib_lookup_arg {
void *lookup_ptr;
const void *lookup_data;
void *result;
struct fib_rule *rule;
u32 table;
int flags;
#define FIB_LOOKUP_NOREF 1
#define FIB_LOOKUP_IGNORE_LINKSTATE 2
};
struct fib_rules_ops {
int family;
struct list_head list;
int rule_size;
int addr_size;
int unresolved_rules;
int nr_goto_rules;
unsigned int fib_rules_seq;
int (*action)(struct fib_rule *,
struct flowi *, int,
struct fib_lookup_arg *);
bool (*suppress)(struct fib_rule *,
struct fib_lookup_arg *);
int (*match)(struct fib_rule *,
struct flowi *, int);
int (*configure)(struct fib_rule *,
struct sk_buff *,
struct fib_rule_hdr *,
struct nlattr **,
struct netlink_ext_ack *);
int (*delete)(struct fib_rule *);
int (*compare)(struct fib_rule *,
struct fib_rule_hdr *,
struct nlattr **);
int (*fill)(struct fib_rule *, struct sk_buff *,
struct fib_rule_hdr *);
size_t (*nlmsg_payload)(struct fib_rule *);
/* Called after modifications to the rules set, must flush
* the route cache if one exists. */
void (*flush_cache)(struct fib_rules_ops *ops);
int nlgroup;
const struct nla_policy *policy;
struct list_head rules_list;
struct module *owner;
struct net *fro_net;
struct rcu_head rcu;
};
struct fib_rule_notifier_info {
struct fib_notifier_info info; /* must be first */
struct fib_rule *rule;
};
#define FRA_GENERIC_POLICY \
[FRA_IIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
[FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
[FRA_PRIORITY] = { .type = NLA_U32 }, \
[FRA_FWMARK] = { .type = NLA_U32 }, \
[FRA_TUN_ID] = { .type = NLA_U64 }, \
[FRA_FWMASK] = { .type = NLA_U32 }, \
[FRA_TABLE] = { .type = NLA_U32 }, \
[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
[FRA_GOTO] = { .type = NLA_U32 }, \
[FRA_L3MDEV] = { .type = NLA_U8 }, \
[FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) }, \
[FRA_PROTOCOL] = { .type = NLA_U8 }, \
[FRA_IP_PROTO] = { .type = NLA_U8 }, \
[FRA_SPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) }, \
[FRA_DPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) }
static inline void fib_rule_get(struct fib_rule *rule)
{
refcount_inc(&rule->refcnt);
}
static inline void fib_rule_put(struct fib_rule *rule)
{
if (refcount_dec_and_test(&rule->refcnt))
kfree_rcu(rule, rcu);
}
#ifdef CONFIG_NET_L3_MASTER_DEV
static inline u32 fib_rule_get_table(struct fib_rule *rule,
struct fib_lookup_arg *arg)
{
return rule->l3mdev ? arg->table : rule->table;
}
#else
static inline u32 fib_rule_get_table(struct fib_rule *rule,
struct fib_lookup_arg *arg)
{
return rule->table;
}
#endif
static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
{
if (nla[FRA_TABLE])
return nla_get_u32(nla[FRA_TABLE]);
return frh->table;
}
static inline bool fib_rule_port_range_set(const struct fib_rule_port_range *range)
{
return range->start != 0 && range->end != 0;
}
static inline bool fib_rule_port_inrange(const struct fib_rule_port_range *a,
__be16 port)
{
return ntohs(port) >= a->start &&
ntohs(port) <= a->end;
}
static inline bool fib_rule_port_range_valid(const struct fib_rule_port_range *a)
{
return a->start != 0 && a->end != 0 && a->end < 0xffff &&
a->start <= a->end;
}
static inline bool fib_rule_port_range_compare(struct fib_rule_port_range *a,
struct fib_rule_port_range *b)
{
return a->start == b->start &&
a->end == b->end;
}
static inline bool fib_rule_requires_fldissect(struct fib_rule *rule)
{
return rule->ip_proto ||
fib_rule_port_range_set(&rule->sport_range) ||
fib_rule_port_range_set(&rule->dport_range);
}
struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *,
struct net *);
void fib_rules_unregister(struct fib_rules_ops *);
int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags,
struct fib_lookup_arg *);
int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table,
u32 flags);
bool fib_rule_matchall(const struct fib_rule *rule);
int fib_rules_dump(struct net *net, struct notifier_block *nb, int family);
unsigned int fib_rules_seq_read(struct net *net, int family);
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack);
int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack);
#endif
+26
View File
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_FIREWIRE_H
#define _NET_FIREWIRE_H
/* Pseudo L2 address */
#define FWNET_ALEN 16
union fwnet_hwaddr {
u8 u[FWNET_ALEN];
/* "Hardware address" defined in RFC2734/RF3146 */
struct {
__be64 uniq_id; /* EUI-64 */
u8 max_rec; /* max packet size */
u8 sspd; /* max speed */
__be16 fifo_hi; /* hi 16bits of FIFO addr */
__be32 fifo_lo; /* lo 32bits of FIFO addr */
} __packed uc;
};
/* Pseudo L2 Header */
#define FWNET_HLEN 18
struct fwnet_header {
u8 h_dest[FWNET_ALEN]; /* destination address */
__be16 h_proto; /* packet type ID field */
} __packed;
#endif
+225
View File
@@ -0,0 +1,225 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
*
* Generic internet FLOW.
*
*/
#ifndef _NET_FLOW_H
#define _NET_FLOW_H
#include <linux/socket.h>
#include <linux/in6.h>
#include <linux/atomic.h>
#include <net/flow_dissector.h>
#include <linux/uidgid.h>
/*
* ifindex generation is per-net namespace, and loopback is
* always the 1st device in ns (see net_dev_init), thus any
* loopback device should get ifindex 1
*/
#define LOOPBACK_IFINDEX 1
struct flowi_tunnel {
__be64 tun_id;
};
struct flowi_common {
int flowic_oif;
int flowic_iif;
__u32 flowic_mark;
__u8 flowic_tos;
__u8 flowic_scope;
__u8 flowic_proto;
__u8 flowic_flags;
#define FLOWI_FLAG_ANYSRC 0x01
#define FLOWI_FLAG_KNOWN_NH 0x02
#define FLOWI_FLAG_SKIP_NH_OIF 0x04
__u32 flowic_secid;
struct flowi_tunnel flowic_tun_key;
kuid_t flowic_uid;
};
union flowi_uli {
struct {
__be16 dport;
__be16 sport;
} ports;
struct {
__u8 type;
__u8 code;
} icmpt;
struct {
__le16 dport;
__le16 sport;
} dnports;
__be32 spi;
__be32 gre_key;
struct {
__u8 type;
} mht;
};
struct flowi4 {
struct flowi_common __fl_common;
#define flowi4_oif __fl_common.flowic_oif
#define flowi4_iif __fl_common.flowic_iif
#define flowi4_mark __fl_common.flowic_mark
#define flowi4_tos __fl_common.flowic_tos
#define flowi4_scope __fl_common.flowic_scope
#define flowi4_proto __fl_common.flowic_proto
#define flowi4_flags __fl_common.flowic_flags
#define flowi4_secid __fl_common.flowic_secid
#define flowi4_tun_key __fl_common.flowic_tun_key
#define flowi4_uid __fl_common.flowic_uid
/* (saddr,daddr) must be grouped, same order as in IP header */
__be32 saddr;
__be32 daddr;
union flowi_uli uli;
#define fl4_sport uli.ports.sport
#define fl4_dport uli.ports.dport
#define fl4_icmp_type uli.icmpt.type
#define fl4_icmp_code uli.icmpt.code
#define fl4_ipsec_spi uli.spi
#define fl4_mh_type uli.mht.type
#define fl4_gre_key uli.gre_key
} __attribute__((__aligned__(BITS_PER_LONG/8)));
static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
__u32 mark, __u8 tos, __u8 scope,
__u8 proto, __u8 flags,
__be32 daddr, __be32 saddr,
__be16 dport, __be16 sport,
kuid_t uid)
{
fl4->flowi4_oif = oif;
fl4->flowi4_iif = LOOPBACK_IFINDEX;
fl4->flowi4_mark = mark;
fl4->flowi4_tos = tos;
fl4->flowi4_scope = scope;
fl4->flowi4_proto = proto;
fl4->flowi4_flags = flags;
fl4->flowi4_secid = 0;
fl4->flowi4_tun_key.tun_id = 0;
fl4->flowi4_uid = uid;
fl4->daddr = daddr;
fl4->saddr = saddr;
fl4->fl4_dport = dport;
fl4->fl4_sport = sport;
}
/* Reset some input parameters after previous lookup */
static inline void flowi4_update_output(struct flowi4 *fl4, int oif, __u8 tos,
__be32 daddr, __be32 saddr)
{
fl4->flowi4_oif = oif;
fl4->flowi4_tos = tos;
fl4->daddr = daddr;
fl4->saddr = saddr;
}
struct flowi6 {
struct flowi_common __fl_common;
#define flowi6_oif __fl_common.flowic_oif
#define flowi6_iif __fl_common.flowic_iif
#define flowi6_mark __fl_common.flowic_mark
#define flowi6_scope __fl_common.flowic_scope
#define flowi6_proto __fl_common.flowic_proto
#define flowi6_flags __fl_common.flowic_flags
#define flowi6_secid __fl_common.flowic_secid
#define flowi6_tun_key __fl_common.flowic_tun_key
#define flowi6_uid __fl_common.flowic_uid
struct in6_addr daddr;
struct in6_addr saddr;
/* Note: flowi6_tos is encoded in flowlabel, too. */
__be32 flowlabel;
union flowi_uli uli;
#define fl6_sport uli.ports.sport
#define fl6_dport uli.ports.dport
#define fl6_icmp_type uli.icmpt.type
#define fl6_icmp_code uli.icmpt.code
#define fl6_ipsec_spi uli.spi
#define fl6_mh_type uli.mht.type
#define fl6_gre_key uli.gre_key
__u32 mp_hash;
} __attribute__((__aligned__(BITS_PER_LONG/8)));
struct flowidn {
struct flowi_common __fl_common;
#define flowidn_oif __fl_common.flowic_oif
#define flowidn_iif __fl_common.flowic_iif
#define flowidn_mark __fl_common.flowic_mark
#define flowidn_scope __fl_common.flowic_scope
#define flowidn_proto __fl_common.flowic_proto
#define flowidn_flags __fl_common.flowic_flags
__le16 daddr;
__le16 saddr;
union flowi_uli uli;
#define fld_sport uli.ports.sport
#define fld_dport uli.ports.dport
} __attribute__((__aligned__(BITS_PER_LONG/8)));
struct flowi {
union {
struct flowi_common __fl_common;
struct flowi4 ip4;
struct flowi6 ip6;
struct flowidn dn;
} u;
#define flowi_oif u.__fl_common.flowic_oif
#define flowi_iif u.__fl_common.flowic_iif
#define flowi_mark u.__fl_common.flowic_mark
#define flowi_tos u.__fl_common.flowic_tos
#define flowi_scope u.__fl_common.flowic_scope
#define flowi_proto u.__fl_common.flowic_proto
#define flowi_flags u.__fl_common.flowic_flags
#define flowi_secid u.__fl_common.flowic_secid
#define flowi_tun_key u.__fl_common.flowic_tun_key
#define flowi_uid u.__fl_common.flowic_uid
} __attribute__((__aligned__(BITS_PER_LONG/8)));
static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
{
return container_of(fl4, struct flowi, u.ip4);
}
static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6)
{
return container_of(fl6, struct flowi, u.ip6);
}
static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn)
{
return container_of(fldn, struct flowi, u.dn);
}
typedef unsigned long flow_compare_t;
static inline unsigned int flow_key_size(u16 family)
{
switch (family) {
case AF_INET:
BUILD_BUG_ON(sizeof(struct flowi4) % sizeof(flow_compare_t));
return sizeof(struct flowi4) / sizeof(flow_compare_t);
case AF_INET6:
BUILD_BUG_ON(sizeof(struct flowi6) % sizeof(flow_compare_t));
return sizeof(struct flowi6) / sizeof(flow_compare_t);
case AF_DECnet:
BUILD_BUG_ON(sizeof(struct flowidn) % sizeof(flow_compare_t));
return sizeof(struct flowidn) / sizeof(flow_compare_t);
}
return 0;
}
__u32 __get_hash_from_flowi6(const struct flowi6 *fl6, struct flow_keys *keys);
#endif
+318
View File
@@ -0,0 +1,318 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_FLOW_DISSECTOR_H
#define _NET_FLOW_DISSECTOR_H
#include <linux/types.h>
#include <linux/in6.h>
#include <linux/siphash.h>
#include <linux/string.h>
#include <uapi/linux/if_ether.h>
/**
* struct flow_dissector_key_control:
* @thoff: Transport header offset
*/
struct flow_dissector_key_control {
u16 thoff;
u16 addr_type;
u32 flags;
};
#define FLOW_DIS_IS_FRAGMENT BIT(0)
#define FLOW_DIS_FIRST_FRAG BIT(1)
#define FLOW_DIS_ENCAPSULATION BIT(2)
enum flow_dissect_ret {
FLOW_DISSECT_RET_OUT_GOOD,
FLOW_DISSECT_RET_OUT_BAD,
FLOW_DISSECT_RET_PROTO_AGAIN,
FLOW_DISSECT_RET_IPPROTO_AGAIN,
FLOW_DISSECT_RET_CONTINUE,
};
/**
* struct flow_dissector_key_basic:
* @thoff: Transport header offset
* @n_proto: Network header protocol (eg. IPv4/IPv6)
* @ip_proto: Transport header protocol (eg. TCP/UDP)
*/
struct flow_dissector_key_basic {
__be16 n_proto;
u8 ip_proto;
u8 padding;
};
struct flow_dissector_key_tags {
u32 flow_label;
};
struct flow_dissector_key_vlan {
u16 vlan_id:12,
vlan_priority:3;
__be16 vlan_tpid;
};
struct flow_dissector_key_mpls {
u32 mpls_ttl:8,
mpls_bos:1,
mpls_tc:3,
mpls_label:20;
};
#define FLOW_DIS_TUN_OPTS_MAX 255
/**
* struct flow_dissector_key_enc_opts:
* @data: tunnel option data
* @len: length of tunnel option data
* @dst_opt_type: tunnel option type
*/
struct flow_dissector_key_enc_opts {
u8 data[FLOW_DIS_TUN_OPTS_MAX]; /* Using IP_TUNNEL_OPTS_MAX is desired
* here but seems difficult to #include
*/
u8 len;
__be16 dst_opt_type;
};
struct flow_dissector_key_keyid {
__be32 keyid;
};
/**
* struct flow_dissector_key_ipv4_addrs:
* @src: source ip address
* @dst: destination ip address
*/
struct flow_dissector_key_ipv4_addrs {
/* (src,dst) must be grouped, in the same way than in IP header */
__be32 src;
__be32 dst;
};
/**
* struct flow_dissector_key_ipv6_addrs:
* @src: source ip address
* @dst: destination ip address
*/
struct flow_dissector_key_ipv6_addrs {
/* (src,dst) must be grouped, in the same way than in IP header */
struct in6_addr src;
struct in6_addr dst;
};
/**
* struct flow_dissector_key_tipc:
* @key: source node address combined with selector
*/
struct flow_dissector_key_tipc {
__be32 key;
};
/**
* struct flow_dissector_key_addrs:
* @v4addrs: IPv4 addresses
* @v6addrs: IPv6 addresses
*/
struct flow_dissector_key_addrs {
union {
struct flow_dissector_key_ipv4_addrs v4addrs;
struct flow_dissector_key_ipv6_addrs v6addrs;
struct flow_dissector_key_tipc tipckey;
};
};
/**
* flow_dissector_key_arp:
* @ports: Operation, source and target addresses for an ARP header
* for Ethernet hardware addresses and IPv4 protocol addresses
* sip: Sender IP address
* tip: Target IP address
* op: Operation
* sha: Sender hardware address
* tpa: Target hardware address
*/
struct flow_dissector_key_arp {
__u32 sip;
__u32 tip;
__u8 op;
unsigned char sha[ETH_ALEN];
unsigned char tha[ETH_ALEN];
};
/**
* flow_dissector_key_tp_ports:
* @ports: port numbers of Transport header
* src: source port number
* dst: destination port number
*/
struct flow_dissector_key_ports {
union {
__be32 ports;
struct {
__be16 src;
__be16 dst;
};
};
};
/**
* flow_dissector_key_icmp:
* @ports: type and code of ICMP header
* icmp: ICMP type (high) and code (low)
* type: ICMP type
* code: ICMP code
*/
struct flow_dissector_key_icmp {
union {
__be16 icmp;
struct {
u8 type;
u8 code;
};
};
};
/**
* struct flow_dissector_key_eth_addrs:
* @src: source Ethernet address
* @dst: destination Ethernet address
*/
struct flow_dissector_key_eth_addrs {
/* (dst,src) must be grouped, in the same way than in ETH header */
unsigned char dst[ETH_ALEN];
unsigned char src[ETH_ALEN];
};
/**
* struct flow_dissector_key_tcp:
* @flags: flags
*/
struct flow_dissector_key_tcp {
__be16 flags;
};
/**
* struct flow_dissector_key_ip:
* @tos: tos
* @ttl: ttl
*/
struct flow_dissector_key_ip {
__u8 tos;
__u8 ttl;
};
enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
FLOW_DISSECTOR_KEY_TIPC, /* struct flow_dissector_key_tipc */
FLOW_DISSECTOR_KEY_ARP, /* struct flow_dissector_key_arp */
FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_flow_vlan */
FLOW_DISSECTOR_KEY_FLOW_LABEL, /* struct flow_dissector_key_flow_tags */
FLOW_DISSECTOR_KEY_GRE_KEYID, /* struct flow_dissector_key_keyid */
FLOW_DISSECTOR_KEY_MPLS_ENTROPY, /* struct flow_dissector_key_keyid */
FLOW_DISSECTOR_KEY_ENC_KEYID, /* struct flow_dissector_key_keyid */
FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
FLOW_DISSECTOR_KEY_ENC_CONTROL, /* struct flow_dissector_key_control */
FLOW_DISSECTOR_KEY_ENC_PORTS, /* struct flow_dissector_key_ports */
FLOW_DISSECTOR_KEY_MPLS, /* struct flow_dissector_key_mpls */
FLOW_DISSECTOR_KEY_TCP, /* struct flow_dissector_key_tcp */
FLOW_DISSECTOR_KEY_IP, /* struct flow_dissector_key_ip */
FLOW_DISSECTOR_KEY_CVLAN, /* struct flow_dissector_key_flow_vlan */
FLOW_DISSECTOR_KEY_ENC_IP, /* struct flow_dissector_key_ip */
FLOW_DISSECTOR_KEY_ENC_OPTS, /* struct flow_dissector_key_enc_opts */
FLOW_DISSECTOR_KEY_MAX,
};
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
#define FLOW_DISSECTOR_F_STOP_AT_L3 BIT(1)
#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(2)
#define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(3)
struct flow_dissector_key {
enum flow_dissector_key_id key_id;
size_t offset; /* offset of struct flow_dissector_key_*
in target the struct */
};
struct flow_dissector {
unsigned int used_keys; /* each bit repesents presence of one key id */
unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
};
struct flow_keys_basic {
struct flow_dissector_key_control control;
struct flow_dissector_key_basic basic;
};
struct flow_keys {
struct flow_dissector_key_control control;
#define FLOW_KEYS_HASH_START_FIELD basic
struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT);
struct flow_dissector_key_tags tags;
struct flow_dissector_key_vlan vlan;
struct flow_dissector_key_vlan cvlan;
struct flow_dissector_key_keyid keyid;
struct flow_dissector_key_ports ports;
struct flow_dissector_key_addrs addrs;
};
#define FLOW_KEYS_HASH_OFFSET \
offsetof(struct flow_keys, FLOW_KEYS_HASH_START_FIELD)
__be32 flow_get_u32_src(const struct flow_keys *flow);
__be32 flow_get_u32_dst(const struct flow_keys *flow);
extern struct flow_dissector flow_keys_dissector;
extern struct flow_dissector flow_keys_basic_dissector;
/* struct flow_keys_digest:
*
* This structure is used to hold a digest of the full flow keys. This is a
* larger "hash" of a flow to allow definitively matching specific flows where
* the 32 bit skb->hash is not large enough. The size is limited to 16 bytes so
* that it can be used in CB of skb (see sch_choke for an example).
*/
#define FLOW_KEYS_DIGEST_LEN 16
struct flow_keys_digest {
u8 data[FLOW_KEYS_DIGEST_LEN];
};
void make_flow_keys_digest(struct flow_keys_digest *digest,
const struct flow_keys *flow);
static inline bool flow_keys_have_l4(const struct flow_keys *keys)
{
return (keys->ports.ports || keys->tags.flow_label);
}
u32 flow_hash_from_keys(struct flow_keys *keys);
static inline bool dissector_uses_key(const struct flow_dissector *flow_dissector,
enum flow_dissector_key_id key_id)
{
return flow_dissector->used_keys & (1 << key_id);
}
static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissector,
enum flow_dissector_key_id key_id,
void *target_container)
{
return ((char *)target_container) + flow_dissector->offset[key_id];
}
static inline void
flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
struct flow_dissector_key_basic *key_basic)
{
memset(key_control, 0, sizeof(*key_control));
memset(key_basic, 0, sizeof(*key_basic));
}
#endif
+20
View File
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_FOU_H
#define __NET_FOU_H
#include <linux/skbuff.h>
#include <net/flow.h>
#include <net/gue.h>
#include <net/ip_tunnels.h>
#include <net/udp.h>
size_t fou_encap_hlen(struct ip_tunnel_encap *e);
size_t gue_encap_hlen(struct ip_tunnel_encap *e);
int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
u8 *protocol, __be16 *sport, int type);
int __gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
u8 *protocol, __be16 *sport, int type);
#endif
+105
View File
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2016 Qualcomm Atheros, Inc
*
* GPL v2
*
* Based on net/sched/sch_fq_codel.c
*/
#ifndef __NET_SCHED_FQ_H
#define __NET_SCHED_FQ_H
struct fq_tin;
/**
* struct fq_flow - per traffic flow queue
*
* @tin: owner of this flow. Used to manage collisions, i.e. when a packet
* hashes to an index which points to a flow that is already owned by a
* different tin the packet is destined to. In such case the implementer
* must provide a fallback flow
* @flowchain: can be linked to fq_tin's new_flows or old_flows. Used for DRR++
* (deficit round robin) based round robin queuing similar to the one
* found in net/sched/sch_fq_codel.c
* @backlogchain: can be linked to other fq_flow and fq. Used to keep track of
* fat flows and efficient head-dropping if packet limit is reached
* @queue: sk_buff queue to hold packets
* @backlog: number of bytes pending in the queue. The number of packets can be
* found in @queue.qlen
* @deficit: used for DRR++
*/
struct fq_flow {
struct fq_tin *tin;
struct list_head flowchain;
struct list_head backlogchain;
struct sk_buff_head queue;
u32 backlog;
int deficit;
};
/**
* struct fq_tin - a logical container of fq_flows
*
* Used to group fq_flows into a logical aggregate. DRR++ scheme is used to
* pull interleaved packets out of the associated flows.
*
* @new_flows: linked list of fq_flow
* @old_flows: linked list of fq_flow
*/
struct fq_tin {
struct list_head new_flows;
struct list_head old_flows;
u32 backlog_bytes;
u32 backlog_packets;
u32 overlimit;
u32 collisions;
u32 flows;
u32 tx_bytes;
u32 tx_packets;
};
/**
* struct fq - main container for fair queuing purposes
*
* @backlogs: linked to fq_flows. Used to maintain fat flows for efficient
* head-dropping when @backlog reaches @limit
* @limit: max number of packets that can be queued across all flows
* @backlog: number of packets queued across all flows
*/
struct fq {
struct fq_flow *flows;
struct list_head backlogs;
spinlock_t lock;
u32 flows_cnt;
siphash_key_t perturbation;
u32 limit;
u32 memory_limit;
u32 memory_usage;
u32 quantum;
u32 backlog;
u32 overlimit;
u32 overmemory;
u32 collisions;
};
typedef struct sk_buff *fq_tin_dequeue_t(struct fq *,
struct fq_tin *,
struct fq_flow *flow);
typedef void fq_skb_free_t(struct fq *,
struct fq_tin *,
struct fq_flow *,
struct sk_buff *);
/* Return %true to filter (drop) the frame. */
typedef bool fq_skb_filter_t(struct fq *,
struct fq_tin *,
struct fq_flow *,
struct sk_buff *,
void *);
typedef struct fq_flow *fq_flow_get_default_t(struct fq *,
struct fq_tin *,
int idx,
struct sk_buff *);
#endif
+337
View File
@@ -0,0 +1,337 @@
/*
* Copyright (c) 2016 Qualcomm Atheros, Inc
*
* GPL v2
*
* Based on net/sched/sch_fq_codel.c
*/
#ifndef __NET_SCHED_FQ_IMPL_H
#define __NET_SCHED_FQ_IMPL_H
#include <net/fq.h>
/* functions that are embedded into includer */
static void fq_adjust_removal(struct fq *fq,
struct fq_flow *flow,
struct sk_buff *skb)
{
struct fq_tin *tin = flow->tin;
tin->backlog_bytes -= skb->len;
tin->backlog_packets--;
flow->backlog -= skb->len;
fq->backlog--;
fq->memory_usage -= skb->truesize;
}
static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow)
{
struct fq_flow *i;
if (flow->backlog == 0) {
list_del_init(&flow->backlogchain);
} else {
i = flow;
list_for_each_entry_continue(i, &fq->backlogs, backlogchain)
if (i->backlog < flow->backlog)
break;
list_move_tail(&flow->backlogchain,
&i->backlogchain);
}
}
static struct sk_buff *fq_flow_dequeue(struct fq *fq,
struct fq_flow *flow)
{
struct sk_buff *skb;
lockdep_assert_held(&fq->lock);
skb = __skb_dequeue(&flow->queue);
if (!skb)
return NULL;
fq_adjust_removal(fq, flow, skb);
fq_rejigger_backlog(fq, flow);
return skb;
}
static struct sk_buff *fq_tin_dequeue(struct fq *fq,
struct fq_tin *tin,
fq_tin_dequeue_t dequeue_func)
{
struct fq_flow *flow;
struct list_head *head;
struct sk_buff *skb;
lockdep_assert_held(&fq->lock);
begin:
head = &tin->new_flows;
if (list_empty(head)) {
head = &tin->old_flows;
if (list_empty(head))
return NULL;
}
flow = list_first_entry(head, struct fq_flow, flowchain);
if (flow->deficit <= 0) {
flow->deficit += fq->quantum;
list_move_tail(&flow->flowchain,
&tin->old_flows);
goto begin;
}
skb = dequeue_func(fq, tin, flow);
if (!skb) {
/* force a pass through old_flows to prevent starvation */
if ((head == &tin->new_flows) &&
!list_empty(&tin->old_flows)) {
list_move_tail(&flow->flowchain, &tin->old_flows);
} else {
list_del_init(&flow->flowchain);
flow->tin = NULL;
}
goto begin;
}
flow->deficit -= skb->len;
tin->tx_bytes += skb->len;
tin->tx_packets++;
return skb;
}
static struct fq_flow *fq_flow_classify(struct fq *fq,
struct fq_tin *tin,
struct sk_buff *skb,
fq_flow_get_default_t get_default_func)
{
struct fq_flow *flow;
u32 hash;
u32 idx;
lockdep_assert_held(&fq->lock);
hash = skb_get_hash_perturb(skb, &fq->perturbation);
idx = reciprocal_scale(hash, fq->flows_cnt);
flow = &fq->flows[idx];
if (flow->tin && flow->tin != tin) {
flow = get_default_func(fq, tin, idx, skb);
tin->collisions++;
fq->collisions++;
}
if (!flow->tin)
tin->flows++;
return flow;
}
static void fq_recalc_backlog(struct fq *fq,
struct fq_tin *tin,
struct fq_flow *flow)
{
struct fq_flow *i;
if (list_empty(&flow->backlogchain))
list_add_tail(&flow->backlogchain, &fq->backlogs);
i = flow;
list_for_each_entry_continue_reverse(i, &fq->backlogs,
backlogchain)
if (i->backlog > flow->backlog)
break;
list_move(&flow->backlogchain, &i->backlogchain);
}
static void fq_tin_enqueue(struct fq *fq,
struct fq_tin *tin,
struct sk_buff *skb,
fq_skb_free_t free_func,
fq_flow_get_default_t get_default_func)
{
struct fq_flow *flow;
bool oom;
lockdep_assert_held(&fq->lock);
flow = fq_flow_classify(fq, tin, skb, get_default_func);
flow->tin = tin;
flow->backlog += skb->len;
tin->backlog_bytes += skb->len;
tin->backlog_packets++;
fq->memory_usage += skb->truesize;
fq->backlog++;
fq_recalc_backlog(fq, tin, flow);
if (list_empty(&flow->flowchain)) {
flow->deficit = fq->quantum;
list_add_tail(&flow->flowchain,
&tin->new_flows);
}
__skb_queue_tail(&flow->queue, skb);
oom = (fq->memory_usage > fq->memory_limit);
while (fq->backlog > fq->limit || oom) {
flow = list_first_entry_or_null(&fq->backlogs,
struct fq_flow,
backlogchain);
if (!flow)
return;
skb = fq_flow_dequeue(fq, flow);
if (!skb)
return;
free_func(fq, flow->tin, flow, skb);
flow->tin->overlimit++;
fq->overlimit++;
if (oom) {
fq->overmemory++;
oom = (fq->memory_usage > fq->memory_limit);
}
}
}
static void fq_flow_filter(struct fq *fq,
struct fq_flow *flow,
fq_skb_filter_t filter_func,
void *filter_data,
fq_skb_free_t free_func)
{
struct fq_tin *tin = flow->tin;
struct sk_buff *skb, *tmp;
lockdep_assert_held(&fq->lock);
skb_queue_walk_safe(&flow->queue, skb, tmp) {
if (!filter_func(fq, tin, flow, skb, filter_data))
continue;
__skb_unlink(skb, &flow->queue);
fq_adjust_removal(fq, flow, skb);
free_func(fq, tin, flow, skb);
}
fq_rejigger_backlog(fq, flow);
}
static void fq_tin_filter(struct fq *fq,
struct fq_tin *tin,
fq_skb_filter_t filter_func,
void *filter_data,
fq_skb_free_t free_func)
{
struct fq_flow *flow;
lockdep_assert_held(&fq->lock);
list_for_each_entry(flow, &tin->new_flows, flowchain)
fq_flow_filter(fq, flow, filter_func, filter_data, free_func);
list_for_each_entry(flow, &tin->old_flows, flowchain)
fq_flow_filter(fq, flow, filter_func, filter_data, free_func);
}
static void fq_flow_reset(struct fq *fq,
struct fq_flow *flow,
fq_skb_free_t free_func)
{
struct sk_buff *skb;
while ((skb = fq_flow_dequeue(fq, flow)))
free_func(fq, flow->tin, flow, skb);
if (!list_empty(&flow->flowchain))
list_del_init(&flow->flowchain);
if (!list_empty(&flow->backlogchain))
list_del_init(&flow->backlogchain);
flow->tin = NULL;
WARN_ON_ONCE(flow->backlog);
}
static void fq_tin_reset(struct fq *fq,
struct fq_tin *tin,
fq_skb_free_t free_func)
{
struct list_head *head;
struct fq_flow *flow;
for (;;) {
head = &tin->new_flows;
if (list_empty(head)) {
head = &tin->old_flows;
if (list_empty(head))
break;
}
flow = list_first_entry(head, struct fq_flow, flowchain);
fq_flow_reset(fq, flow, free_func);
}
WARN_ON_ONCE(tin->backlog_bytes);
WARN_ON_ONCE(tin->backlog_packets);
}
static void fq_flow_init(struct fq_flow *flow)
{
INIT_LIST_HEAD(&flow->flowchain);
INIT_LIST_HEAD(&flow->backlogchain);
__skb_queue_head_init(&flow->queue);
}
static void fq_tin_init(struct fq_tin *tin)
{
INIT_LIST_HEAD(&tin->new_flows);
INIT_LIST_HEAD(&tin->old_flows);
}
static int fq_init(struct fq *fq, int flows_cnt)
{
int i;
memset(fq, 0, sizeof(fq[0]));
INIT_LIST_HEAD(&fq->backlogs);
spin_lock_init(&fq->lock);
fq->flows_cnt = max_t(u32, flows_cnt, 1);
get_random_bytes(&fq->perturbation, sizeof(fq->perturbation));
fq->quantum = 300;
fq->limit = 8192;
fq->memory_limit = 16 << 20; /* 16 MBytes */
fq->flows = kvcalloc(fq->flows_cnt, sizeof(fq->flows[0]), GFP_KERNEL);
if (!fq->flows)
return -ENOMEM;
for (i = 0; i < fq->flows_cnt; i++)
fq_flow_init(&fq->flows[i]);
return 0;
}
static void fq_reset(struct fq *fq,
fq_skb_free_t free_func)
{
int i;
for (i = 0; i < fq->flows_cnt; i++)
fq_flow_reset(fq, &fq->flows[i], free_func);
kvfree(fq->flows);
fq->flows = NULL;
}
#endif
+130
View File
@@ -0,0 +1,130 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_GARP_H
#define _NET_GARP_H
#include <net/stp.h>
#define GARP_PROTOCOL_ID 0x1
#define GARP_END_MARK 0x0
struct garp_pdu_hdr {
__be16 protocol;
};
struct garp_msg_hdr {
u8 attrtype;
};
enum garp_attr_event {
GARP_LEAVE_ALL,
GARP_JOIN_EMPTY,
GARP_JOIN_IN,
GARP_LEAVE_EMPTY,
GARP_LEAVE_IN,
GARP_EMPTY,
};
struct garp_attr_hdr {
u8 len;
u8 event;
u8 data[];
};
struct garp_skb_cb {
u8 cur_type;
};
static inline struct garp_skb_cb *garp_cb(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct garp_skb_cb) >
FIELD_SIZEOF(struct sk_buff, cb));
return (struct garp_skb_cb *)skb->cb;
}
enum garp_applicant_state {
GARP_APPLICANT_INVALID,
GARP_APPLICANT_VA,
GARP_APPLICANT_AA,
GARP_APPLICANT_QA,
GARP_APPLICANT_LA,
GARP_APPLICANT_VP,
GARP_APPLICANT_AP,
GARP_APPLICANT_QP,
GARP_APPLICANT_VO,
GARP_APPLICANT_AO,
GARP_APPLICANT_QO,
__GARP_APPLICANT_MAX
};
#define GARP_APPLICANT_MAX (__GARP_APPLICANT_MAX - 1)
enum garp_event {
GARP_EVENT_REQ_JOIN,
GARP_EVENT_REQ_LEAVE,
GARP_EVENT_R_JOIN_IN,
GARP_EVENT_R_JOIN_EMPTY,
GARP_EVENT_R_EMPTY,
GARP_EVENT_R_LEAVE_IN,
GARP_EVENT_R_LEAVE_EMPTY,
GARP_EVENT_TRANSMIT_PDU,
__GARP_EVENT_MAX
};
#define GARP_EVENT_MAX (__GARP_EVENT_MAX - 1)
enum garp_action {
GARP_ACTION_NONE,
GARP_ACTION_S_JOIN_IN,
GARP_ACTION_S_LEAVE_EMPTY,
};
struct garp_attr {
struct rb_node node;
enum garp_applicant_state state;
u8 type;
u8 dlen;
unsigned char data[];
};
enum garp_applications {
GARP_APPLICATION_GVRP,
__GARP_APPLICATION_MAX
};
#define GARP_APPLICATION_MAX (__GARP_APPLICATION_MAX - 1)
struct garp_application {
enum garp_applications type;
unsigned int maxattr;
struct stp_proto proto;
};
struct garp_applicant {
struct garp_application *app;
struct net_device *dev;
struct timer_list join_timer;
spinlock_t lock;
struct sk_buff_head queue;
struct sk_buff *pdu;
struct rb_root gid;
struct rcu_head rcu;
};
struct garp_port {
struct garp_applicant __rcu *applicants[GARP_APPLICATION_MAX + 1];
struct rcu_head rcu;
};
int garp_register_application(struct garp_application *app);
void garp_unregister_application(struct garp_application *app);
int garp_init_applicant(struct net_device *dev, struct garp_application *app);
void garp_uninit_applicant(struct net_device *dev,
struct garp_application *app);
int garp_request_join(const struct net_device *dev,
const struct garp_application *app, const void *data,
u8 len, u8 type);
void garp_request_leave(const struct net_device *dev,
const struct garp_application *app,
const void *data, u8 len, u8 type);
#endif /* _NET_GARP_H */
+73
View File
@@ -0,0 +1,73 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_GEN_STATS_H
#define __NET_GEN_STATS_H
#include <linux/gen_stats.h>
#include <linux/socket.h>
#include <linux/rtnetlink.h>
#include <linux/pkt_sched.h>
struct gnet_stats_basic_cpu {
struct gnet_stats_basic_packed bstats;
struct u64_stats_sync syncp;
};
struct net_rate_estimator;
struct gnet_dump {
spinlock_t * lock;
struct sk_buff * skb;
struct nlattr * tail;
/* Backward compatibility */
int compat_tc_stats;
int compat_xstats;
int padattr;
void * xstats;
int xstats_len;
struct tc_stats tc_stats;
};
int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
struct gnet_dump *d, int padattr);
int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
int tc_stats_type, int xstats_type,
spinlock_t *lock, struct gnet_dump *d,
int padattr);
int gnet_stats_copy_basic(const seqcount_t *running,
struct gnet_dump *d,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
void __gnet_stats_copy_basic(const seqcount_t *running,
struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
int gnet_stats_copy_rate_est(struct gnet_dump *d,
struct net_rate_estimator __rcu **ptr);
int gnet_stats_copy_queue(struct gnet_dump *d,
struct gnet_stats_queue __percpu *cpu_q,
struct gnet_stats_queue *q, __u32 qlen);
void __gnet_stats_copy_queue(struct gnet_stats_queue *qstats,
const struct gnet_stats_queue __percpu *cpu_q,
const struct gnet_stats_queue *q, __u32 qlen);
int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
int gnet_stats_finish_copy(struct gnet_dump *d);
int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
struct net_rate_estimator __rcu **rate_est,
spinlock_t *lock,
seqcount_t *running, struct nlattr *opt);
void gen_kill_estimator(struct net_rate_estimator __rcu **ptr);
int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
struct net_rate_estimator __rcu **ptr,
spinlock_t *lock,
seqcount_t *running, struct nlattr *opt);
bool gen_estimator_active(struct net_rate_estimator __rcu **ptr);
bool gen_estimator_read(struct net_rate_estimator __rcu **ptr,
struct gnet_stats_rate_est64 *sample);
#endif
+387
View File
@@ -0,0 +1,387 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_GENERIC_NETLINK_H
#define __NET_GENERIC_NETLINK_H
#include <linux/genetlink.h>
#include <net/netlink.h>
#include <net/net_namespace.h>
#define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
/**
* struct genl_multicast_group - generic netlink multicast group
* @name: name of the multicast group, names are per-family
*/
struct genl_multicast_group {
char name[GENL_NAMSIZ];
};
struct genl_ops;
struct genl_info;
/**
* struct genl_family - generic netlink family
* @id: protocol family identifier (private)
* @hdrsize: length of user specific header in bytes
* @name: name of family
* @version: protocol version
* @maxattr: maximum number of attributes supported
* @netnsok: set to true if the family can handle network
* namespaces and should be presented in all of them
* @parallel_ops: operations can be called in parallel and aren't
* synchronized by the core genetlink code
* @pre_doit: called before an operation's doit callback, it may
* do additional, common, filtering and return an error
* @post_doit: called after an operation's doit callback, it may
* undo operations done by pre_doit, for example release locks
* @mcast_bind: a socket bound to the given multicast group (which
* is given as the offset into the groups array)
* @mcast_unbind: a socket was unbound from the given multicast group.
* Note that unbind() will not be called symmetrically if the
* generic netlink family is removed while there are still open
* sockets.
* @attrbuf: buffer to store parsed attributes (private)
* @mcgrps: multicast groups used by this family
* @n_mcgrps: number of multicast groups
* @mcgrp_offset: starting number of multicast group IDs in this family
* (private)
* @ops: the operations supported by this family
* @n_ops: number of operations supported by this family
*/
struct genl_family {
int id; /* private */
unsigned int hdrsize;
char name[GENL_NAMSIZ];
unsigned int version;
unsigned int maxattr;
bool netnsok;
bool parallel_ops;
int (*pre_doit)(const struct genl_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
void (*post_doit)(const struct genl_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
int (*mcast_bind)(struct net *net, int group);
void (*mcast_unbind)(struct net *net, int group);
struct nlattr ** attrbuf; /* private */
const struct genl_ops * ops;
const struct genl_multicast_group *mcgrps;
unsigned int n_ops;
unsigned int n_mcgrps;
unsigned int mcgrp_offset; /* private */
struct module *module;
};
struct nlattr **genl_family_attrbuf(const struct genl_family *family);
/**
* struct genl_info - receiving information
* @snd_seq: sending sequence number
* @snd_portid: netlink portid of sender
* @nlhdr: netlink message header
* @genlhdr: generic netlink message header
* @userhdr: user specific header
* @attrs: netlink attributes
* @_net: network namespace
* @user_ptr: user pointers
* @extack: extended ACK report struct
*/
struct genl_info {
u32 snd_seq;
u32 snd_portid;
struct nlmsghdr * nlhdr;
struct genlmsghdr * genlhdr;
void * userhdr;
struct nlattr ** attrs;
possible_net_t _net;
void * user_ptr[2];
struct netlink_ext_ack *extack;
};
static inline struct net *genl_info_net(struct genl_info *info)
{
return read_pnet(&info->_net);
}
static inline void genl_info_net_set(struct genl_info *info, struct net *net)
{
write_pnet(&info->_net, net);
}
#define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG((info)->extack, msg)
static inline int genl_err_attr(struct genl_info *info, int err,
struct nlattr *attr)
{
info->extack->bad_attr = attr;
return err;
}
/**
* struct genl_ops - generic netlink operations
* @cmd: command identifier
* @internal_flags: flags used by the family
* @flags: flags
* @policy: attribute validation policy
* @doit: standard command callback
* @start: start callback for dumps
* @dumpit: callback for dumpers
* @done: completion callback for dumps
*/
struct genl_ops {
const struct nla_policy *policy;
int (*doit)(struct sk_buff *skb,
struct genl_info *info);
int (*start)(struct netlink_callback *cb);
int (*dumpit)(struct sk_buff *skb,
struct netlink_callback *cb);
int (*done)(struct netlink_callback *cb);
u8 cmd;
u8 internal_flags;
u8 flags;
};
int genl_register_family(struct genl_family *family);
int genl_unregister_family(const struct genl_family *family);
void genl_notify(const struct genl_family *family, struct sk_buff *skb,
struct genl_info *info, u32 group, gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
const struct genl_family *family, int flags, u8 cmd);
/**
* genlmsg_nlhdr - Obtain netlink header from user specified header
* @user_hdr: user header as returned from genlmsg_put()
*
* Returns pointer to netlink header.
*/
static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr)
{
return (struct nlmsghdr *)((char *)user_hdr -
GENL_HDRLEN -
NLMSG_HDRLEN);
}
/**
* genlmsg_parse - parse attributes of a genetlink message
* @nlh: netlink message header
* @family: genetlink message family
* @tb: destination array with maxtype+1 elements
* @maxtype: maximum attribute type to be expected
* @policy: validation policy
* @extack: extended ACK report struct
*/
static inline int genlmsg_parse(const struct nlmsghdr *nlh,
const struct genl_family *family,
struct nlattr *tb[], int maxtype,
const struct nla_policy *policy,
struct netlink_ext_ack *extack)
{
return nlmsg_parse(nlh, family->hdrsize + GENL_HDRLEN, tb, maxtype,
policy, extack);
}
/**
* genl_dump_check_consistent - check if sequence is consistent and advertise if not
* @cb: netlink callback structure that stores the sequence number
* @user_hdr: user header as returned from genlmsg_put()
*
* Cf. nl_dump_check_consistent(), this just provides a wrapper to make it
* simpler to use with generic netlink.
*/
static inline void genl_dump_check_consistent(struct netlink_callback *cb,
void *user_hdr)
{
nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr));
}
/**
* genlmsg_put_reply - Add generic netlink header to a reply message
* @skb: socket buffer holding the message
* @info: receiver info
* @family: generic netlink family
* @flags: netlink message flags
* @cmd: generic netlink command
*
* Returns pointer to user specific header
*/
static inline void *genlmsg_put_reply(struct sk_buff *skb,
struct genl_info *info,
const struct genl_family *family,
int flags, u8 cmd)
{
return genlmsg_put(skb, info->snd_portid, info->snd_seq, family,
flags, cmd);
}
/**
* genlmsg_end - Finalize a generic netlink message
* @skb: socket buffer the message is stored in
* @hdr: user specific header
*/
static inline void genlmsg_end(struct sk_buff *skb, void *hdr)
{
nlmsg_end(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_cancel - Cancel construction of a generic netlink message
* @skb: socket buffer the message is stored in
* @hdr: generic netlink message header
*/
static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
{
if (hdr)
nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_multicast_netns - multicast a netlink message to a specific netns
* @family: the generic netlink family
* @net: the net namespace
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast_netns(const struct genl_family *family,
struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
}
/**
* genlmsg_multicast - multicast a netlink message to the default netns
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast(const struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags)
{
return genlmsg_multicast_netns(family, &init_net, skb,
portid, group, flags);
}
/**
* genlmsg_multicast_allns - multicast a netlink message to all net namespaces
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: offset of multicast group in groups array
* @flags: allocation flags
*
* This function must hold the RTNL or rcu_read_lock().
*/
int genlmsg_multicast_allns(const struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags);
/**
* genlmsg_unicast - unicast a netlink message
* @skb: netlink message as socket buffer
* @portid: netlink portid of the destination socket
*/
static inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32 portid)
{
return nlmsg_unicast(net->genl_sock, skb, portid);
}
/**
* genlmsg_reply - reply to a request
* @skb: netlink message to be sent back
* @info: receiver information
*/
static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
{
return genlmsg_unicast(genl_info_net(info), skb, info->snd_portid);
}
/**
* gennlmsg_data - head of message payload
* @gnlh: genetlink message header
*/
static inline void *genlmsg_data(const struct genlmsghdr *gnlh)
{
return ((unsigned char *) gnlh + GENL_HDRLEN);
}
/**
* genlmsg_len - length of message payload
* @gnlh: genetlink message header
*/
static inline int genlmsg_len(const struct genlmsghdr *gnlh)
{
struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
NLMSG_HDRLEN);
return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_msg_size - length of genetlink message not including padding
* @payload: length of message payload
*/
static inline int genlmsg_msg_size(int payload)
{
return GENL_HDRLEN + payload;
}
/**
* genlmsg_total_size - length of genetlink message including padding
* @payload: length of message payload
*/
static inline int genlmsg_total_size(int payload)
{
return NLMSG_ALIGN(genlmsg_msg_size(payload));
}
/**
* genlmsg_new - Allocate a new generic netlink message
* @payload: size of the message payload
* @flags: the type of memory to allocate.
*/
static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
{
return nlmsg_new(genlmsg_total_size(payload), flags);
}
/**
* genl_set_err - report error to genetlink broadcast listeners
* @family: the generic netlink family
* @net: the network namespace to report the error to
* @portid: the PORTID of a process that we want to skip (if any)
* @group: the broadcast group that will notice the error
* (this is the offset of the multicast group in the groups array)
* @code: error code, must be negative (as usual in kernelspace)
*
* This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option.
*/
static inline int genl_set_err(const struct genl_family *family,
struct net *net, u32 portid,
u32 group, int code)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return netlink_set_err(net->genl_sock, portid, group, code);
}
static inline int genl_has_listeners(const struct genl_family *family,
struct net *net, unsigned int group)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return netlink_has_listeners(net->genl_sock, group);
}
#endif /* __NET_GENERIC_NETLINK_H */
+68
View File
@@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_GENEVE_H
#define __NET_GENEVE_H 1
#include <net/udp_tunnel.h>
/* Geneve Header:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Ver| Opt Len |O|C| Rsvd. | Protocol Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Virtual Network Identifier (VNI) | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Variable Length Options |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Option Header:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Option Class | Type |R|R|R| Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Variable Option Data |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct geneve_opt {
__be16 opt_class;
u8 type;
#ifdef __LITTLE_ENDIAN_BITFIELD
u8 length:5;
u8 r3:1;
u8 r2:1;
u8 r1:1;
#else
u8 r1:1;
u8 r2:1;
u8 r3:1;
u8 length:5;
#endif
u8 opt_data[];
};
#define GENEVE_CRIT_OPT_TYPE (1 << 7)
struct genevehdr {
#ifdef __LITTLE_ENDIAN_BITFIELD
u8 opt_len:6;
u8 ver:2;
u8 rsvd1:6;
u8 critical:1;
u8 oam:1;
#else
u8 ver:2;
u8 opt_len:6;
u8 oam:1;
u8 critical:1;
u8 rsvd1:6;
#endif
__be16 proto_type;
u8 vni[3];
u8 rsvd2;
struct geneve_opt options[];
};
#ifdef CONFIG_INET
struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
u8 name_assign_type, u16 dst_port);
#endif /*ifdef CONFIG_INET */
#endif /*ifdef__NET_GENEVE_H */
+145
View File
@@ -0,0 +1,145 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_GRE_H
#define __LINUX_GRE_H
#include <linux/skbuff.h>
#include <net/ip_tunnels.h>
struct gre_base_hdr {
__be16 flags;
__be16 protocol;
} __packed;
struct gre_full_hdr {
struct gre_base_hdr fixed_header;
__be16 csum;
__be16 reserved1;
__be32 key;
__be32 seq;
} __packed;
#define GRE_HEADER_SECTION 4
#define GREPROTO_CISCO 0
#define GREPROTO_PPTP 1
#define GREPROTO_MAX 2
#define GRE_IP_PROTO_MAX 2
struct gre_protocol {
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
};
int gre_add_protocol(const struct gre_protocol *proto, u8 version);
int gre_del_protocol(const struct gre_protocol *proto, u8 version);
struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
u8 name_assign_type);
int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
bool *csum_err, __be16 proto, int nhs);
bool is_gretap_dev(const struct net_device *dev);
bool is_ip6gretap_dev(const struct net_device *dev);
static inline int gre_calc_hlen(__be16 o_flags)
{
int addend = 4;
if (o_flags & TUNNEL_CSUM)
addend += 4;
if (o_flags & TUNNEL_KEY)
addend += 4;
if (o_flags & TUNNEL_SEQ)
addend += 4;
return addend;
}
static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
{
__be16 tflags = 0;
if (flags & GRE_CSUM)
tflags |= TUNNEL_CSUM;
if (flags & GRE_ROUTING)
tflags |= TUNNEL_ROUTING;
if (flags & GRE_KEY)
tflags |= TUNNEL_KEY;
if (flags & GRE_SEQ)
tflags |= TUNNEL_SEQ;
if (flags & GRE_STRICT)
tflags |= TUNNEL_STRICT;
if (flags & GRE_REC)
tflags |= TUNNEL_REC;
if (flags & GRE_VERSION)
tflags |= TUNNEL_VERSION;
return tflags;
}
static inline __be16 gre_tnl_flags_to_gre_flags(__be16 tflags)
{
__be16 flags = 0;
if (tflags & TUNNEL_CSUM)
flags |= GRE_CSUM;
if (tflags & TUNNEL_ROUTING)
flags |= GRE_ROUTING;
if (tflags & TUNNEL_KEY)
flags |= GRE_KEY;
if (tflags & TUNNEL_SEQ)
flags |= GRE_SEQ;
if (tflags & TUNNEL_STRICT)
flags |= GRE_STRICT;
if (tflags & TUNNEL_REC)
flags |= GRE_REC;
if (tflags & TUNNEL_VERSION)
flags |= GRE_VERSION;
return flags;
}
static inline __sum16 gre_checksum(struct sk_buff *skb)
{
__wsum csum;
if (skb->ip_summed == CHECKSUM_PARTIAL)
csum = lco_csum(skb);
else
csum = skb_checksum(skb, 0, skb->len, 0);
return csum_fold(csum);
}
static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
__be16 flags, __be16 proto,
__be32 key, __be32 seq)
{
struct gre_base_hdr *greh;
skb_push(skb, hdr_len);
skb_set_inner_protocol(skb, proto);
skb_reset_transport_header(skb);
greh = (struct gre_base_hdr *)skb->data;
greh->flags = gre_tnl_flags_to_gre_flags(flags);
greh->protocol = proto;
if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
if (flags & TUNNEL_SEQ) {
*ptr = seq;
ptr--;
}
if (flags & TUNNEL_KEY) {
*ptr = key;
ptr--;
}
if (flags & TUNNEL_CSUM &&
!(skb_shinfo(skb)->gso_type &
(SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
*ptr = 0;
*(__sum16 *)ptr = gre_checksum(skb);
}
}
}
#endif
+19
View File
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_GRO_CELLS_H
#define _NET_GRO_CELLS_H
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
struct gro_cell;
struct gro_cells {
struct gro_cell __percpu *cells;
};
int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb);
int gro_cells_init(struct gro_cells *gcells, struct net_device *dev);
void gro_cells_destroy(struct gro_cells *gcells);
#endif
+35
View File
@@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _GTP_H_
#define _GTP_H_
/* General GTP protocol related definitions. */
#define GTP0_PORT 3386
#define GTP1U_PORT 2152
#define GTP_TPDU 255
struct gtp0_header { /* According to GSM TS 09.60. */
__u8 flags;
__u8 type;
__be16 length;
__be16 seq;
__be16 flow;
__u8 number;
__u8 spare[3];
__be64 tid;
} __attribute__ ((packed));
struct gtp1_header { /* According to 3GPP TS 29.060. */
__u8 flags;
__u8 type;
__be16 length;
__be32 tid;
} __attribute__ ((packed));
#define GTP1_F_NPDU 0x01
#define GTP1_F_SEQ 0x02
#define GTP1_F_EXTHDR 0x04
#define GTP1_F_MASK 0x07
#endif
+117
View File
@@ -0,0 +1,117 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_GUE_H
#define __NET_GUE_H
/* Definitions for the GUE header, standard and private flags, lengths
* of optional fields are below.
*
* Diagram of GUE header:
*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Ver|C| Hlen | Proto/ctype | Standard flags |P|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* ~ Fields (optional) ~
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Private flags (optional, P bit is set) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* ~ Private fields (optional) ~
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* C bit indicates contol message when set, data message when unset.
* For a control message, proto/ctype is interpreted as a type of
* control message. For data messages, proto/ctype is the IP protocol
* of the next header.
*
* P bit indicates private flags field is present. The private flags
* may refer to options placed after this field.
*/
struct guehdr {
union {
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 hlen:5,
control:1,
version:2;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:2,
control:1,
hlen:5;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 proto_ctype;
__be16 flags;
};
__be32 word;
};
};
/* Standard flags in GUE header */
#define GUE_FLAG_PRIV htons(1<<0) /* Private flags are in options */
#define GUE_LEN_PRIV 4
#define GUE_FLAGS_ALL (GUE_FLAG_PRIV)
/* Private flags in the private option extension */
#define GUE_PFLAG_REMCSUM htonl(1 << 31)
#define GUE_PLEN_REMCSUM 4
#define GUE_PFLAGS_ALL (GUE_PFLAG_REMCSUM)
/* Functions to compute options length corresponding to flags.
* If we ever have a lot of flags this can be potentially be
* converted to a more optimized algorithm (table lookup
* for instance).
*/
static inline size_t guehdr_flags_len(__be16 flags)
{
return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0);
}
static inline size_t guehdr_priv_flags_len(__be32 flags)
{
return 0;
}
/* Validate standard and private flags. Returns non-zero (meaning invalid)
* if there is an unknown standard or private flags, or the options length for
* the flags exceeds the options length specific in hlen of the GUE header.
*/
static inline int validate_gue_flags(struct guehdr *guehdr, size_t optlen)
{
__be16 flags = guehdr->flags;
size_t len;
if (flags & ~GUE_FLAGS_ALL)
return 1;
len = guehdr_flags_len(flags);
if (len > optlen)
return 1;
if (flags & GUE_FLAG_PRIV) {
/* Private flags are last four bytes accounted in
* guehdr_flags_len
*/
__be32 pflags = *(__be32 *)((void *)&guehdr[1] +
len - GUE_LEN_PRIV);
if (pflags & ~GUE_PFLAGS_ALL)
return 1;
len += guehdr_priv_flags_len(pflags);
if (len > optlen)
return 1;
}
return 0;
}
#endif
+29
View File
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _HWBM_H
#define _HWBM_H
struct hwbm_pool {
/* Capacity of the pool */
int size;
/* Size of the buffers managed */
int frag_size;
/* Number of buffers currently used by this pool */
int buf_num;
/* constructor called during alocation */
int (*construct)(struct hwbm_pool *bm_pool, void *buf);
/* protect acces to the buffer counter*/
spinlock_t lock;
/* private data */
void *priv;
};
#ifdef CONFIG_HWBM
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf);
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp);
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp);
#else
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {}
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; }
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
{ return 0; }
#endif /* CONFIG_HWBM */
#endif /* _HWBM_H */
+65
View File
@@ -0,0 +1,65 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the ICMP module.
*
* Version: @(#)icmp.h 1.0.4 05/13/93
*
* Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ICMP_H
#define _ICMP_H
#include <linux/icmp.h>
#include <net/inet_sock.h>
#include <net/snmp.h>
#include <net/ip.h>
struct icmp_err {
int errno;
unsigned int fatal:1;
};
extern const struct icmp_err icmp_err_convert[];
#define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field)
#define __ICMP_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.icmp_statistics, field)
#define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256)
#define ICMPMSGIN_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field)
struct dst_entry;
struct net_proto_family;
struct sk_buff;
struct net;
void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
const struct ip_options *opt);
static inline void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
{
__icmp_send(skb_in, type, code, info, &IPCB(skb_in)->opt);
}
#if IS_ENABLED(CONFIG_NF_NAT)
void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info);
#else
static inline void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info)
{
struct ip_options opts = { 0 };
__icmp_send(skb_in, type, code, info, &opts);
}
#endif
int icmp_rcv(struct sk_buff *skb);
void icmp_err(struct sk_buff *skb, u32 info);
int icmp_init(void);
void icmp_out_count(struct net *net, unsigned char type);
#endif /* _ICMP_H */
+338
View File
@@ -0,0 +1,338 @@
/*
* Copyright (c) 2017 Intel Deutschland GmbH
* Copyright (c) 2018 Intel Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __RADIOTAP_H
#define __RADIOTAP_H
#include <linux/kernel.h>
#include <asm/unaligned.h>
/**
* struct ieee82011_radiotap_header - base radiotap header
*/
struct ieee80211_radiotap_header {
/**
* @it_version: radiotap version, always 0
*/
uint8_t it_version;
/**
* @it_pad: padding (or alignment)
*/
uint8_t it_pad;
/**
* @it_len: overall radiotap header length
*/
__le16 it_len;
/**
* @it_present: (first) present word
*/
__le32 it_present;
} __packed;
/* version is always 0 */
#define PKTHDR_RADIOTAP_VERSION 0
/* see the radiotap website for the descriptions */
enum ieee80211_radiotap_presence {
IEEE80211_RADIOTAP_TSFT = 0,
IEEE80211_RADIOTAP_FLAGS = 1,
IEEE80211_RADIOTAP_RATE = 2,
IEEE80211_RADIOTAP_CHANNEL = 3,
IEEE80211_RADIOTAP_FHSS = 4,
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
IEEE80211_RADIOTAP_ANTENNA = 11,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
IEEE80211_RADIOTAP_RX_FLAGS = 14,
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
/* 18 is XChannel, but it's not defined yet */
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
IEEE80211_RADIOTAP_VHT = 21,
IEEE80211_RADIOTAP_TIMESTAMP = 22,
IEEE80211_RADIOTAP_HE = 23,
IEEE80211_RADIOTAP_HE_MU = 24,
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31
};
/* for IEEE80211_RADIOTAP_FLAGS */
enum ieee80211_radiotap_flags {
IEEE80211_RADIOTAP_F_CFP = 0x01,
IEEE80211_RADIOTAP_F_SHORTPRE = 0x02,
IEEE80211_RADIOTAP_F_WEP = 0x04,
IEEE80211_RADIOTAP_F_FRAG = 0x08,
IEEE80211_RADIOTAP_F_FCS = 0x10,
IEEE80211_RADIOTAP_F_DATAPAD = 0x20,
IEEE80211_RADIOTAP_F_BADFCS = 0x40,
};
/* for IEEE80211_RADIOTAP_CHANNEL */
enum ieee80211_radiotap_channel_flags {
IEEE80211_CHAN_CCK = 0x0020,
IEEE80211_CHAN_OFDM = 0x0040,
IEEE80211_CHAN_2GHZ = 0x0080,
IEEE80211_CHAN_5GHZ = 0x0100,
IEEE80211_CHAN_DYN = 0x0400,
IEEE80211_CHAN_HALF = 0x4000,
IEEE80211_CHAN_QUARTER = 0x8000,
};
/* for IEEE80211_RADIOTAP_RX_FLAGS */
enum ieee80211_radiotap_rx_flags {
IEEE80211_RADIOTAP_F_RX_BADPLCP = 0x0002,
};
/* for IEEE80211_RADIOTAP_TX_FLAGS */
enum ieee80211_radiotap_tx_flags {
IEEE80211_RADIOTAP_F_TX_FAIL = 0x0001,
IEEE80211_RADIOTAP_F_TX_CTS = 0x0002,
IEEE80211_RADIOTAP_F_TX_RTS = 0x0004,
IEEE80211_RADIOTAP_F_TX_NOACK = 0x0008,
};
/* for IEEE80211_RADIOTAP_MCS "have" flags */
enum ieee80211_radiotap_mcs_have {
IEEE80211_RADIOTAP_MCS_HAVE_BW = 0x01,
IEEE80211_RADIOTAP_MCS_HAVE_MCS = 0x02,
IEEE80211_RADIOTAP_MCS_HAVE_GI = 0x04,
IEEE80211_RADIOTAP_MCS_HAVE_FMT = 0x08,
IEEE80211_RADIOTAP_MCS_HAVE_FEC = 0x10,
IEEE80211_RADIOTAP_MCS_HAVE_STBC = 0x20,
};
enum ieee80211_radiotap_mcs_flags {
IEEE80211_RADIOTAP_MCS_BW_MASK = 0x03,
IEEE80211_RADIOTAP_MCS_BW_20 = 0,
IEEE80211_RADIOTAP_MCS_BW_40 = 1,
IEEE80211_RADIOTAP_MCS_BW_20L = 2,
IEEE80211_RADIOTAP_MCS_BW_20U = 3,
IEEE80211_RADIOTAP_MCS_SGI = 0x04,
IEEE80211_RADIOTAP_MCS_FMT_GF = 0x08,
IEEE80211_RADIOTAP_MCS_FEC_LDPC = 0x10,
IEEE80211_RADIOTAP_MCS_STBC_MASK = 0x60,
IEEE80211_RADIOTAP_MCS_STBC_1 = 1,
IEEE80211_RADIOTAP_MCS_STBC_2 = 2,
IEEE80211_RADIOTAP_MCS_STBC_3 = 3,
IEEE80211_RADIOTAP_MCS_STBC_SHIFT = 5,
};
/* for IEEE80211_RADIOTAP_AMPDU_STATUS */
enum ieee80211_radiotap_ampdu_flags {
IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN = 0x0001,
IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN = 0x0002,
IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN = 0x0004,
IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008,
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010,
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020,
IEEE80211_RADIOTAP_AMPDU_EOF = 0x0040,
IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN = 0x0080,
};
/* for IEEE80211_RADIOTAP_VHT */
enum ieee80211_radiotap_vht_known {
IEEE80211_RADIOTAP_VHT_KNOWN_STBC = 0x0001,
IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA = 0x0002,
IEEE80211_RADIOTAP_VHT_KNOWN_GI = 0x0004,
IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS = 0x0008,
IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM = 0x0010,
IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED = 0x0020,
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH = 0x0040,
IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID = 0x0080,
IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID = 0x0100,
};
enum ieee80211_radiotap_vht_flags {
IEEE80211_RADIOTAP_VHT_FLAG_STBC = 0x01,
IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA = 0x02,
IEEE80211_RADIOTAP_VHT_FLAG_SGI = 0x04,
IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 = 0x08,
IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM = 0x10,
IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED = 0x20,
};
enum ieee80211_radiotap_vht_coding {
IEEE80211_RADIOTAP_CODING_LDPC_USER0 = 0x01,
IEEE80211_RADIOTAP_CODING_LDPC_USER1 = 0x02,
IEEE80211_RADIOTAP_CODING_LDPC_USER2 = 0x04,
IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08,
};
/* for IEEE80211_RADIOTAP_TIMESTAMP */
enum ieee80211_radiotap_timestamp_unit_spos {
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F,
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS = 0x0000,
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US = 0x0001,
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS = 0x0003,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK = 0x00F0,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU = 0x0000,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ = 0x0010,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU = 0x0020,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU = 0x0030,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN = 0x00F0,
};
enum ieee80211_radiotap_timestamp_flags {
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT = 0x00,
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT = 0x01,
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02,
};
struct ieee80211_radiotap_he {
__le16 data1, data2, data3, data4, data5, data6;
};
enum ieee80211_radiotap_he_bits {
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3,
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004,
IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008,
IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010,
IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020,
IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040,
IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080,
IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100,
IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000,
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000,
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000,
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001,
IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002,
IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004,
IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008,
IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010,
IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020,
IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040,
IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000,
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000,
IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f,
IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040,
IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080,
IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00,
IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000,
IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000,
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000,
IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000,
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f,
IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10,
IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030,
IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0,
IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1,
IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3,
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700,
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000,
IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000,
IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000,
IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f,
IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010,
IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00,
IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000,
};
struct ieee80211_radiotap_he_mu {
__le16 flags1, flags2;
u8 ru_ch1[4];
u8 ru_ch2[4];
};
enum ieee80211_radiotap_he_mu_bits {
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN= 0x0400,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800,
};
/**
* ieee80211_get_radiotap_len - get radiotap header length
*/
static inline u16 ieee80211_get_radiotap_len(const char *data)
{
struct ieee80211_radiotap_header *hdr = (void *)data;
return get_unaligned_le16(&hdr->it_len);
}
#endif /* __RADIOTAP_H */
+349
View File
@@ -0,0 +1,349 @@
/*
* An interface between IEEE802.15.4 device and rest of the kernel.
*
* Copyright (C) 2007-2012 Siemens AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Written by:
* Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
* Maxim Osipov <maxim.osipov@siemens.com>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
#ifndef IEEE802154_NETDEVICE_H
#define IEEE802154_NETDEVICE_H
#include <net/af_ieee802154.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/ieee802154.h>
#include <net/cfg802154.h>
struct ieee802154_sechdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
u8 level:3,
key_id_mode:2,
reserved:3;
#elif defined(__BIG_ENDIAN_BITFIELD)
u8 reserved:3,
key_id_mode:2,
level:3;
#else
#error "Please fix <asm/byteorder.h>"
#endif
u8 key_id;
__le32 frame_counter;
union {
__le32 short_src;
__le64 extended_src;
};
};
struct ieee802154_hdr_fc {
#if defined(__LITTLE_ENDIAN_BITFIELD)
u16 type:3,
security_enabled:1,
frame_pending:1,
ack_request:1,
intra_pan:1,
reserved:3,
dest_addr_mode:2,
version:2,
source_addr_mode:2;
#elif defined(__BIG_ENDIAN_BITFIELD)
u16 reserved:1,
intra_pan:1,
ack_request:1,
frame_pending:1,
security_enabled:1,
type:3,
source_addr_mode:2,
version:2,
dest_addr_mode:2,
reserved2:2;
#else
#error "Please fix <asm/byteorder.h>"
#endif
};
struct ieee802154_hdr {
struct ieee802154_hdr_fc fc;
u8 seq;
struct ieee802154_addr source;
struct ieee802154_addr dest;
struct ieee802154_sechdr sec;
};
/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
* the contents of hdr will be, and the actual value of those bits in
* hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
* version, if SECEN is set.
*/
int ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr);
/* pulls the entire 802.15.4 header off of the skb, including the security
* header, and performs pan id decompression
*/
int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr);
/* parses the frame control, sequence number of address fields in a given skb
* and stores them into hdr, performing pan id decompression and length checks
* to be suitable for use in header_ops.parse
*/
int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
struct ieee802154_hdr *hdr);
/* parses the full 802.15.4 header a given skb and stores them into hdr,
* performing pan id decompression and length checks to be suitable for use in
* header_ops.parse
*/
int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
static inline int
ieee802154_sechdr_authtag_len(const struct ieee802154_sechdr *sec)
{
switch (sec->level) {
case IEEE802154_SCF_SECLEVEL_MIC32:
case IEEE802154_SCF_SECLEVEL_ENC_MIC32:
return 4;
case IEEE802154_SCF_SECLEVEL_MIC64:
case IEEE802154_SCF_SECLEVEL_ENC_MIC64:
return 8;
case IEEE802154_SCF_SECLEVEL_MIC128:
case IEEE802154_SCF_SECLEVEL_ENC_MIC128:
return 16;
case IEEE802154_SCF_SECLEVEL_NONE:
case IEEE802154_SCF_SECLEVEL_ENC:
default:
return 0;
}
}
static inline int ieee802154_hdr_length(struct sk_buff *skb)
{
struct ieee802154_hdr hdr;
int len = ieee802154_hdr_pull(skb, &hdr);
if (len > 0)
skb_push(skb, len);
return len;
}
static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1,
const struct ieee802154_addr *a2)
{
if (a1->pan_id != a2->pan_id || a1->mode != a2->mode)
return false;
if ((a1->mode == IEEE802154_ADDR_LONG &&
a1->extended_addr != a2->extended_addr) ||
(a1->mode == IEEE802154_ADDR_SHORT &&
a1->short_addr != a2->short_addr))
return false;
return true;
}
static inline __le64 ieee802154_devaddr_from_raw(const void *raw)
{
u64 temp;
memcpy(&temp, raw, IEEE802154_ADDR_LEN);
return (__force __le64)swab64(temp);
}
static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr)
{
u64 temp = swab64((__force u64)addr);
memcpy(raw, &temp, IEEE802154_ADDR_LEN);
}
static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a,
const struct ieee802154_addr_sa *sa)
{
a->mode = sa->addr_type;
a->pan_id = cpu_to_le16(sa->pan_id);
switch (a->mode) {
case IEEE802154_ADDR_SHORT:
a->short_addr = cpu_to_le16(sa->short_addr);
break;
case IEEE802154_ADDR_LONG:
a->extended_addr = ieee802154_devaddr_from_raw(sa->hwaddr);
break;
}
}
static inline void ieee802154_addr_to_sa(struct ieee802154_addr_sa *sa,
const struct ieee802154_addr *a)
{
sa->addr_type = a->mode;
sa->pan_id = le16_to_cpu(a->pan_id);
switch (a->mode) {
case IEEE802154_ADDR_SHORT:
sa->short_addr = le16_to_cpu(a->short_addr);
break;
case IEEE802154_ADDR_LONG:
ieee802154_devaddr_to_raw(sa->hwaddr, a->extended_addr);
break;
}
}
/*
* A control block of skb passed between the ARPHRD_IEEE802154 device
* and other stack parts.
*/
struct ieee802154_mac_cb {
u8 lqi;
u8 type;
bool ackreq;
bool secen;
bool secen_override;
u8 seclevel;
bool seclevel_override;
struct ieee802154_addr source;
struct ieee802154_addr dest;
};
static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
{
return (struct ieee802154_mac_cb *)skb->cb;
}
static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct ieee802154_mac_cb) > sizeof(skb->cb));
memset(skb->cb, 0, sizeof(struct ieee802154_mac_cb));
return mac_cb(skb);
}
enum {
IEEE802154_LLSEC_DEVKEY_IGNORE,
IEEE802154_LLSEC_DEVKEY_RESTRICT,
IEEE802154_LLSEC_DEVKEY_RECORD,
__IEEE802154_LLSEC_DEVKEY_MAX,
};
#define IEEE802154_MAC_SCAN_ED 0
#define IEEE802154_MAC_SCAN_ACTIVE 1
#define IEEE802154_MAC_SCAN_PASSIVE 2
#define IEEE802154_MAC_SCAN_ORPHAN 3
struct ieee802154_mac_params {
s8 transmit_power;
u8 min_be;
u8 max_be;
u8 csma_retries;
s8 frame_retries;
bool lbt;
struct wpan_phy_cca cca;
s32 cca_ed_level;
};
struct wpan_phy;
enum {
IEEE802154_LLSEC_PARAM_ENABLED = BIT(0),
IEEE802154_LLSEC_PARAM_FRAME_COUNTER = BIT(1),
IEEE802154_LLSEC_PARAM_OUT_LEVEL = BIT(2),
IEEE802154_LLSEC_PARAM_OUT_KEY = BIT(3),
IEEE802154_LLSEC_PARAM_KEY_SOURCE = BIT(4),
IEEE802154_LLSEC_PARAM_PAN_ID = BIT(5),
IEEE802154_LLSEC_PARAM_HWADDR = BIT(6),
IEEE802154_LLSEC_PARAM_COORD_HWADDR = BIT(7),
IEEE802154_LLSEC_PARAM_COORD_SHORTADDR = BIT(8),
};
struct ieee802154_llsec_ops {
int (*get_params)(struct net_device *dev,
struct ieee802154_llsec_params *params);
int (*set_params)(struct net_device *dev,
const struct ieee802154_llsec_params *params,
int changed);
int (*add_key)(struct net_device *dev,
const struct ieee802154_llsec_key_id *id,
const struct ieee802154_llsec_key *key);
int (*del_key)(struct net_device *dev,
const struct ieee802154_llsec_key_id *id);
int (*add_dev)(struct net_device *dev,
const struct ieee802154_llsec_device *llsec_dev);
int (*del_dev)(struct net_device *dev, __le64 dev_addr);
int (*add_devkey)(struct net_device *dev,
__le64 device_addr,
const struct ieee802154_llsec_device_key *key);
int (*del_devkey)(struct net_device *dev,
__le64 device_addr,
const struct ieee802154_llsec_device_key *key);
int (*add_seclevel)(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl);
int (*del_seclevel)(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl);
void (*lock_table)(struct net_device *dev);
void (*get_table)(struct net_device *dev,
struct ieee802154_llsec_table **t);
void (*unlock_table)(struct net_device *dev);
};
/*
* This should be located at net_device->ml_priv
*
* get_phy should increment the reference counting on returned phy.
* Use wpan_wpy_put to put that reference.
*/
struct ieee802154_mlme_ops {
/* The following fields are optional (can be NULL). */
int (*assoc_req)(struct net_device *dev,
struct ieee802154_addr *addr,
u8 channel, u8 page, u8 cap);
int (*assoc_resp)(struct net_device *dev,
struct ieee802154_addr *addr,
__le16 short_addr, u8 status);
int (*disassoc_req)(struct net_device *dev,
struct ieee802154_addr *addr,
u8 reason);
int (*start_req)(struct net_device *dev,
struct ieee802154_addr *addr,
u8 channel, u8 page, u8 bcn_ord, u8 sf_ord,
u8 pan_coord, u8 blx, u8 coord_realign);
int (*scan_req)(struct net_device *dev,
u8 type, u32 channels, u8 page, u8 duration);
int (*set_mac_params)(struct net_device *dev,
const struct ieee802154_mac_params *params);
void (*get_mac_params)(struct net_device *dev,
struct ieee802154_mac_params *params);
const struct ieee802154_llsec_ops *llsec;
};
static inline struct ieee802154_mlme_ops *
ieee802154_mlme_ops(const struct net_device *dev)
{
return dev->ml_priv;
}
#endif
+265
View File
@@ -0,0 +1,265 @@
/*
* inet6 interface/address list definitions
* Linux INET6 implementation
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _NET_IF_INET6_H
#define _NET_IF_INET6_H
#include <net/snmp.h>
#include <linux/ipv6.h>
#include <linux/refcount.h>
/* inet6_dev.if_flags */
#define IF_RS_VZW_SENT 0x01 /*add for VzW feature*/
#define IF_RA_OTHERCONF 0x80
#define IF_RA_MANAGED 0x40
#define IF_RA_RCVD 0x20
#define IF_RS_SENT 0x10
#define IF_READY 0x80000000
/* prefix flags */
#define IF_PREFIX_ONLINK 0x01
#define IF_PREFIX_AUTOCONF 0x02
enum {
INET6_IFADDR_STATE_PREDAD,
INET6_IFADDR_STATE_DAD,
INET6_IFADDR_STATE_POSTDAD,
INET6_IFADDR_STATE_ERRDAD,
INET6_IFADDR_STATE_DEAD,
};
struct inet6_ifaddr {
struct in6_addr addr;
__u32 prefix_len;
__u32 rt_priority;
/* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
__u32 valid_lft;
__u32 prefered_lft;
refcount_t refcnt;
spinlock_t lock;
int state;
__u32 flags;
__u8 dad_probes;
__u8 stable_privacy_retry;
__u16 scope;
__u64 dad_nonce;
unsigned long cstamp; /* created timestamp */
unsigned long tstamp; /* updated timestamp */
struct delayed_work dad_work;
struct inet6_dev *idev;
struct fib6_info *rt;
struct hlist_node addr_lst;
struct list_head if_list;
struct list_head tmp_list;
struct inet6_ifaddr *ifpub;
int regen_count;
bool tokenized;
struct rcu_head rcu;
struct in6_addr peer_addr;
};
struct ip6_sf_socklist {
unsigned int sl_max;
unsigned int sl_count;
struct in6_addr sl_addr[0];
};
#define IP6_SFLSIZE(count) (sizeof(struct ip6_sf_socklist) + \
(count) * sizeof(struct in6_addr))
#define IP6_SFBLOCK 10 /* allocate this many at once */
struct ipv6_mc_socklist {
struct in6_addr addr;
int ifindex;
struct ipv6_mc_socklist __rcu *next;
rwlock_t sflock;
unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */
struct ip6_sf_socklist *sflist;
struct rcu_head rcu;
};
struct ip6_sf_list {
struct ip6_sf_list *sf_next;
struct in6_addr sf_addr;
unsigned long sf_count[2]; /* include/exclude counts */
unsigned char sf_gsresp; /* include in g & s response? */
unsigned char sf_oldin; /* change state */
unsigned char sf_crcount; /* retrans. left to send */
};
#define MAF_TIMER_RUNNING 0x01
#define MAF_LAST_REPORTER 0x02
#define MAF_LOADED 0x04
#define MAF_NOREPORT 0x08
#define MAF_GSQUERY 0x10
struct ifmcaddr6 {
struct in6_addr mca_addr;
struct inet6_dev *idev;
struct ifmcaddr6 *next;
struct ip6_sf_list *mca_sources;
struct ip6_sf_list *mca_tomb;
unsigned int mca_sfmode;
unsigned char mca_crcount;
unsigned long mca_sfcount[2];
struct timer_list mca_timer;
unsigned int mca_flags;
int mca_users;
refcount_t mca_refcnt;
spinlock_t mca_lock;
unsigned long mca_cstamp;
unsigned long mca_tstamp;
};
/* Anycast stuff */
struct ipv6_ac_socklist {
struct in6_addr acl_addr;
int acl_ifindex;
struct ipv6_ac_socklist *acl_next;
};
struct ifacaddr6 {
struct in6_addr aca_addr;
struct fib6_info *aca_rt;
struct ifacaddr6 *aca_next;
int aca_users;
refcount_t aca_refcnt;
unsigned long aca_cstamp;
unsigned long aca_tstamp;
};
#define IFA_HOST IPV6_ADDR_LOOPBACK
#define IFA_LINK IPV6_ADDR_LINKLOCAL
#define IFA_SITE IPV6_ADDR_SITELOCAL
struct ipv6_devstat {
struct proc_dir_entry *proc_dir_entry;
DEFINE_SNMP_STAT(struct ipstats_mib, ipv6);
DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev);
DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev);
};
struct inet6_dev {
struct net_device *dev;
struct list_head addr_list;
struct ifmcaddr6 *mc_list;
struct ifmcaddr6 *mc_tomb;
spinlock_t mc_lock;
unsigned char mc_qrv; /* Query Robustness Variable */
unsigned char mc_gq_running;
unsigned char mc_ifc_count;
unsigned char mc_dad_count;
unsigned long mc_v1_seen; /* Max time we stay in MLDv1 mode */
unsigned long mc_qi; /* Query Interval */
unsigned long mc_qri; /* Query Response Interval */
unsigned long mc_maxdelay;
struct timer_list mc_gq_timer; /* general query timer */
struct timer_list mc_ifc_timer; /* interface change timer */
struct timer_list mc_dad_timer; /* dad complete mc timer */
struct ifacaddr6 *ac_list;
rwlock_t lock;
refcount_t refcnt;
__u32 if_flags;
int dead;
u32 desync_factor;
u8 rndid[8];
struct list_head tempaddr_list;
struct in6_addr token;
struct neigh_parms *nd_parms;
struct ipv6_devconf cnf;
struct ipv6_devstat stats;
struct timer_list rs_timer;
__s32 rs_interval; /* in jiffies */
__u8 rs_probes;
unsigned long tstamp; /* ipv6InterfaceTable update timestamp */
struct rcu_head rcu;
};
static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf)
{
/*
* +-------+-------+-------+-------+-------+-------+
* | 33 | 33 | DST13 | DST14 | DST15 | DST16 |
* +-------+-------+-------+-------+-------+-------+
*/
buf[0]= 0x33;
buf[1]= 0x33;
memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32));
}
static inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf)
{
buf[0] = 0x00;
}
static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
const unsigned char *broadcast, char *buf)
{
unsigned char scope = broadcast[5] & 0xF;
buf[0] = 0; /* Reserved */
buf[1] = 0xff; /* Multicast QPN */
buf[2] = 0xff;
buf[3] = 0xff;
buf[4] = 0xff;
buf[5] = 0x10 | scope; /* scope from broadcast address */
buf[6] = 0x60; /* IPv6 signature */
buf[7] = 0x1b;
buf[8] = broadcast[8]; /* P_Key */
buf[9] = broadcast[9];
memcpy(buf + 10, addr->s6_addr + 6, 10);
}
static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr,
const unsigned char *broadcast, char *buf)
{
if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) {
memcpy(buf, broadcast, 4);
} else {
/* v4mapped? */
if ((addr->s6_addr32[0] | addr->s6_addr32[1] |
(addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0)
return -EINVAL;
memcpy(buf, &addr->s6_addr32[3], 4);
}
return 0;
}
#endif
+53
View File
@@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_IFE_H
#define __NET_IFE_H
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <linux/module.h>
#include <uapi/linux/ife.h>
#if IS_ENABLED(CONFIG_NET_IFE)
void *ife_encode(struct sk_buff *skb, u16 metalen);
void *ife_decode(struct sk_buff *skb, u16 *metalen);
void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
u16 *dlen, u16 *totlen);
int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval);
void *ife_tlv_meta_next(void *skbdata);
#else
static inline void *ife_encode(struct sk_buff *skb, u16 metalen)
{
return NULL;
}
static inline void *ife_decode(struct sk_buff *skb, u16 *metalen)
{
return NULL;
}
static inline void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen,
u16 *totlen)
{
return NULL;
}
static inline int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval)
{
return 0;
}
static inline void *ife_tlv_meta_next(void *skbdata)
{
return NULL;
}
#endif
#endif /* __NET_IFE_H */
+18
View File
@@ -0,0 +1,18 @@
/*
* ILA kernel interface
*
* Copyright (c) 2015 Tom Herbert <tom@herbertland.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#ifndef _NET_ILA_H
#define _NET_ILA_H
int ila_xlat_outgoing(struct sk_buff *skb);
int ila_xlat_incoming(struct sk_buff *skb);
#endif /* _NET_ILA_H */
+31
View File
@@ -0,0 +1,31 @@
/*
* NET Generic infrastructure for INET6 connection oriented protocols.
*
* Authors: Many people, see the TCPv6 sources
*
* From code originally in TCPv6
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _INET6_CONNECTION_SOCK_H
#define _INET6_CONNECTION_SOCK_H
#include <linux/types.h>
struct request_sock;
struct sk_buff;
struct sock;
struct sockaddr;
struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6,
const struct request_sock *req, u8 proto);
void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET6_CONNECTION_SOCK_H */
+123
View File
@@ -0,0 +1,123 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Authors: Lotsa people, from code originally in tcp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _INET6_HASHTABLES_H
#define _INET6_HASHTABLES_H
#if IS_ENABLED(CONFIG_IPV6)
#include <linux/in6.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <linux/jhash.h>
#include <net/inet_sock.h>
#include <net/ipv6.h>
#include <net/netns/hash.h>
struct inet_hashinfo;
static inline unsigned int __inet6_ehashfn(const u32 lhash,
const u16 lport,
const u32 fhash,
const __be16 fport,
const u32 initval)
{
const u32 ports = (((u32)lport) << 16) | (__force u32)fport;
return jhash_3words(lhash, fhash, ports, initval);
}
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
* we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
*
* The sockhash lock must be held as a reader here.
*/
struct sock *__inet6_lookup_established(struct net *net,
struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const __be16 sport,
const struct in6_addr *daddr,
const u16 hnum, const int dif,
const int sdif);
struct sock *inet6_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
const struct in6_addr *saddr,
const __be16 sport,
const struct in6_addr *daddr,
const unsigned short hnum,
const int dif, const int sdif);
static inline struct sock *__inet6_lookup(struct net *net,
struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
const struct in6_addr *saddr,
const __be16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif, const int sdif,
bool *refcounted)
{
struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr,
sport, daddr, hnum,
dif, sdif);
*refcounted = true;
if (sk)
return sk;
*refcounted = false;
return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
daddr, hnum, dif, sdif);
}
static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
const __be16 sport,
const __be16 dport,
int iif, int sdif,
bool *refcounted)
{
struct sock *sk = skb_steal_sock(skb);
*refcounted = true;
if (sk)
return sk;
return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
doff, &ipv6_hdr(skb)->saddr, sport,
&ipv6_hdr(skb)->daddr, ntohs(dport),
iif, sdif, refcounted);
}
struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
const struct in6_addr *saddr, const __be16 sport,
const struct in6_addr *daddr, const __be16 dport,
const int dif);
int inet6_hash(struct sock *sk);
#endif /* IS_ENABLED(CONFIG_IPV6) */
#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif, __sdif) \
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_family == AF_INET6) && \
ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \
ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \
(!(__sk)->sk_bound_dev_if || \
((__sk)->sk_bound_dev_if == (__dif)) || \
((__sk)->sk_bound_dev_if == (__sdif))) && \
net_eq(sock_net(__sk), (__net)))
#endif /* _INET6_HASHTABLES_H */
+57
View File
@@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _INET_COMMON_H
#define _INET_COMMON_H
extern const struct proto_ops inet_stream_ops;
extern const struct proto_ops inet_dgram_ops;
/*
* INET4 prototypes used by INET6
*/
struct msghdr;
struct sock;
struct sockaddr;
struct socket;
int inet_release(struct socket *sock);
int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags);
int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags, int is_sendmsg);
int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags);
int inet_accept(struct socket *sock, struct socket *newsock, int flags,
bool kern);
int inet_sendmsg(struct socket *sock, struct msghdr *msg, size_t size);
ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
size_t size, int flags);
int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags);
int inet_shutdown(struct socket *sock, int how);
int inet_listen(struct socket *sock, int backlog);
void inet_sock_destruct(struct sock *sk);
int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
bool force_bind_address_no_port, bool with_lock);
int inet_getname(struct socket *sock, struct sockaddr *uaddr,
int peer);
int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int inet_ctl_sock_create(struct sock **sk, unsigned short family,
unsigned short type, unsigned char protocol,
struct net *net);
int inet_recv_error(struct sock *sk, struct msghdr *msg, int len,
int *addr_len);
struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb);
int inet_gro_complete(struct sk_buff *skb, int nhoff);
struct sk_buff *inet_gso_segment(struct sk_buff *skb,
netdev_features_t features);
static inline void inet_ctl_sock_destroy(struct sock *sk)
{
if (sk)
sock_release(sk->sk_socket);
}
#endif
+321
View File
@@ -0,0 +1,321 @@
/*
* NET Generic infrastructure for INET connection oriented protocols.
*
* Definitions for inet_connection_sock
*
* Authors: Many people, see the TCP sources
*
* From code originally in TCP
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _INET_CONNECTION_SOCK_H
#define _INET_CONNECTION_SOCK_H
#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/poll.h>
#include <linux/kernel.h>
#include <net/inet_sock.h>
#include <net/request_sock.h>
/* Cancel timers, when they are not required. */
#undef INET_CSK_CLEAR_TIMERS
struct inet_bind_bucket;
struct tcp_congestion_ops;
/*
* Pointers to address related TCP functions
* (i.e. things that depend on the address family)
*/
struct inet_connection_sock_af_ops {
int (*queue_xmit)(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
void (*send_check)(struct sock *sk, struct sk_buff *skb);
int (*rebuild_header)(struct sock *sk);
void (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
int (*conn_request)(struct sock *sk, struct sk_buff *skb);
struct sock *(*syn_recv_sock)(const struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst,
struct request_sock *req_unhash,
bool *own_req);
u16 net_header_len;
u16 net_frag_header_len;
u16 sockaddr_len;
int (*setsockopt)(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
int (*getsockopt)(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
#ifdef CONFIG_COMPAT
int (*compat_setsockopt)(struct sock *sk,
int level, int optname,
char __user *optval, unsigned int optlen);
int (*compat_getsockopt)(struct sock *sk,
int level, int optname,
char __user *optval, int __user *optlen);
#endif
void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
void (*mtu_reduced)(struct sock *sk);
};
/** inet_connection_sock - INET connection oriented sock
*
* @icsk_accept_queue: FIFO of established children
* @icsk_bind_hash: Bind node
* @icsk_timeout: Timeout
* @icsk_retransmit_timer: Resend (no ack)
* @icsk_rto: Retransmit timeout
* @icsk_pmtu_cookie Last pmtu seen by socket
* @icsk_ca_ops Pluggable congestion control hook
* @icsk_af_ops Operations which are AF_INET{4,6} specific
* @icsk_ulp_ops Pluggable ULP control hook
* @icsk_ulp_data ULP private data
* @icsk_clean_acked Clean acked data hook
* @icsk_listen_portaddr_node hash to the portaddr listener hashtable
* @icsk_ca_state: Congestion control state
* @icsk_retransmits: Number of unrecovered [RTO] timeouts
* @icsk_pending: Scheduled timer event
* @icsk_backoff: Backoff
* @icsk_syn_retries: Number of allowed SYN (or equivalent) retries
* @icsk_probes_out: unanswered 0 window probes
* @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options)
* @icsk_ack: Delayed ACK control data
* @icsk_mtup; MTU probing control data
*/
struct inet_connection_sock {
/* inet_sock has to be the first member! */
struct inet_sock icsk_inet;
struct request_sock_queue icsk_accept_queue;
struct inet_bind_bucket *icsk_bind_hash;
unsigned long icsk_timeout;
struct timer_list icsk_retransmit_timer;
struct timer_list icsk_delack_timer;
__u32 icsk_rto;
__u32 icsk_pmtu_cookie;
const struct tcp_congestion_ops *icsk_ca_ops;
const struct inet_connection_sock_af_ops *icsk_af_ops;
const struct tcp_ulp_ops *icsk_ulp_ops;
void *icsk_ulp_data;
void (*icsk_clean_acked)(struct sock *sk, u32 acked_seq);
struct hlist_node icsk_listen_portaddr_node;
unsigned int (*icsk_sync_mss)(struct sock *sk, u32 pmtu);
__u8 icsk_ca_state:6,
icsk_ca_setsockopt:1,
icsk_ca_dst_locked:1;
__u8 icsk_retransmits;
__u8 icsk_pending;
__u8 icsk_backoff;
__u8 icsk_syn_retries;
__u8 icsk_probes_out;
__u16 icsk_ext_hdr_len;
struct {
__u8 pending; /* ACK is pending */
__u8 quick; /* Scheduled number of quick acks */
__u8 pingpong; /* The session is interactive */
__u8 blocked; /* Delayed ACK was blocked by socket lock */
__u32 ato; /* Predicted tick of soft clock */
unsigned long timeout; /* Currently scheduled timeout */
__u32 lrcvtime; /* timestamp of last received data packet */
__u16 last_seg_size; /* Size of last incoming segment */
__u16 rcv_mss; /* MSS used for delayed ACK decisions */
} icsk_ack;
struct {
int enabled;
/* Range of MTUs to search */
int search_high;
int search_low;
/* Information on the current probe. */
int probe_size;
u32 probe_timestamp;
} icsk_mtup;
u32 icsk_user_timeout;
u64 icsk_ca_priv[104 / sizeof(u64)];
#define ICSK_CA_PRIV_SIZE (13 * sizeof(u64))
};
#define ICSK_TIME_RETRANS 1 /* Retransmit timer */
#define ICSK_TIME_DACK 2 /* Delayed ack timer */
#define ICSK_TIME_PROBE0 3 /* Zero window probe timer */
#define ICSK_TIME_EARLY_RETRANS 4 /* Early retransmit timer */
#define ICSK_TIME_LOSS_PROBE 5 /* Tail loss probe timer */
#define ICSK_TIME_REO_TIMEOUT 6 /* Reordering timer */
static inline struct inet_connection_sock *inet_csk(const struct sock *sk)
{
return (struct inet_connection_sock *)sk;
}
static inline void *inet_csk_ca(const struct sock *sk)
{
return (void *)inet_csk(sk)->icsk_ca_priv;
}
struct sock *inet_csk_clone_lock(const struct sock *sk,
const struct request_sock *req,
const gfp_t priority);
enum inet_csk_ack_state_t {
ICSK_ACK_SCHED = 1,
ICSK_ACK_TIMER = 2,
ICSK_ACK_PUSHED = 4,
ICSK_ACK_PUSHED2 = 8,
ICSK_ACK_NOW = 16 /* Send the next ACK immediately (once) */
};
void inet_csk_init_xmit_timers(struct sock *sk,
void (*retransmit_handler)(struct timer_list *),
void (*delack_handler)(struct timer_list *),
void (*keepalive_handler)(struct timer_list *));
void inet_csk_clear_xmit_timers(struct sock *sk);
static inline void inet_csk_schedule_ack(struct sock *sk)
{
inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_SCHED;
}
static inline int inet_csk_ack_scheduled(const struct sock *sk)
{
return inet_csk(sk)->icsk_ack.pending & ICSK_ACK_SCHED;
}
static inline void inet_csk_delack_init(struct sock *sk)
{
memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack));
}
void inet_csk_delete_keepalive_timer(struct sock *sk);
void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout);
static inline void inet_csk_clear_xmit_timer(struct sock *sk, const int what)
{
struct inet_connection_sock *icsk = inet_csk(sk);
if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
icsk->icsk_pending = 0;
#ifdef INET_CSK_CLEAR_TIMERS
sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
#endif
} else if (what == ICSK_TIME_DACK) {
icsk->icsk_ack.blocked = icsk->icsk_ack.pending = 0;
#ifdef INET_CSK_CLEAR_TIMERS
sk_stop_timer(sk, &icsk->icsk_delack_timer);
#endif
} else {
pr_debug("inet_csk BUG: unknown timer value\n");
}
}
/*
* Reset the retransmission timer
*/
static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,
unsigned long when,
const unsigned long max_when)
{
struct inet_connection_sock *icsk = inet_csk(sk);
if (when > max_when) {
pr_debug("reset_xmit_timer: sk=%p %d when=0x%lx, caller=%p\n",
sk, what, when, (void *)_THIS_IP_);
when = max_when;
}
if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0 ||
what == ICSK_TIME_EARLY_RETRANS || what == ICSK_TIME_LOSS_PROBE ||
what == ICSK_TIME_REO_TIMEOUT) {
icsk->icsk_pending = what;
icsk->icsk_timeout = jiffies + when;
sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
} else if (what == ICSK_TIME_DACK) {
icsk->icsk_ack.pending |= ICSK_ACK_TIMER;
icsk->icsk_ack.timeout = jiffies + when;
sk_reset_timer(sk, &icsk->icsk_delack_timer, icsk->icsk_ack.timeout);
} else {
pr_debug("inet_csk BUG: unknown timer value\n");
}
}
static inline unsigned long
inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
unsigned long max_when)
{
u64 when = (u64)icsk->icsk_rto << icsk->icsk_backoff;
return (unsigned long)min_t(u64, when, max_when);
}
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern);
int inet_csk_get_port(struct sock *sk, unsigned short snum);
struct dst_entry *inet_csk_route_req(const struct sock *sk, struct flowi4 *fl4,
const struct request_sock *req);
struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
struct sock *newsk,
const struct request_sock *req);
struct sock *inet_csk_reqsk_queue_add(struct sock *sk,
struct request_sock *req,
struct sock *child);
void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
unsigned long timeout);
struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child,
struct request_sock *req,
bool own_req);
static inline void inet_csk_reqsk_queue_added(struct sock *sk)
{
reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue);
}
static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
{
return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
}
static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
{
return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog;
}
bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req);
void inet_csk_reqsk_queue_drop_and_put(struct sock *sk, struct request_sock *req);
void inet_csk_destroy_sock(struct sock *sk);
void inet_csk_prepare_forced_close(struct sock *sk);
/*
* LISTEN is a special case for poll..
*/
static inline __poll_t inet_csk_listen_poll(const struct sock *sk)
{
return !reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue) ?
(EPOLLIN | EPOLLRDNORM) : 0;
}
int inet_csk_listen_start(struct sock *sk, int backlog);
void inet_csk_listen_stop(struct sock *sk);
void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
/* update the fast reuse flag when adding a socket */
void inet_csk_update_fastreuse(struct inet_bind_bucket *tb,
struct sock *sk);
struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET_CONNECTION_SOCK_H */
Loaded 100 of 80519 files, more files were not shown because too many files have changed in this diff. Show more