Skip to content

Commit 7c65787

Browse files
Arnaldo Carvalho de MeloDavid S. Miller
Arnaldo Carvalho de Melo
authored and
David S. Miller
committed
[DCCP]: Initial implementation
Development to this point was done on a subversion repository at: http://oops.ghostprotocols.net:81/cgi-bin/viewcvs.cgi/dccp-2.6/ This repository will be kept at this site for the foreseable future, so that interested parties can see the history of this code, attributions, etc. If I ever decide to take this offline I'll provide the full history at some other suitable place. Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c4365c9 commit 7c65787

File tree

22 files changed

+7746
-0
lines changed

22 files changed

+7746
-0
lines changed

include/linux/dccp.h

Lines changed: 432 additions & 0 deletions
Large diffs are not rendered by default.

include/linux/in.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum {
3232
IPPROTO_PUP = 12, /* PUP protocol */
3333
IPPROTO_UDP = 17, /* User Datagram Protocol */
3434
IPPROTO_IDP = 22, /* XNS IDP protocol */
35+
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */
3536
IPPROTO_RSVP = 46, /* RSVP protocol */
3637
IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
3738

include/linux/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum sock_type {
8484
SOCK_RAW = 3,
8585
SOCK_RDM = 4,
8686
SOCK_SEQPACKET = 5,
87+
SOCK_DCCP = 6,
8788
SOCK_PACKET = 10,
8889
};
8990

include/linux/socket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ struct ucred {
271271
#define SOL_IRDA 266
272272
#define SOL_NETBEUI 267
273273
#define SOL_LLC 268
274+
#define SOL_DCCP 269
274275

275276
/* IPX options */
276277
#define IPX_TYPE 1

net/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ source "net/bridge/netfilter/Kconfig"
147147

148148
endif
149149

150+
source "net/dccp/Kconfig"
150151
source "net/sctp/Kconfig"
151152
source "net/atm/Kconfig"
152153
source "net/bridge/Kconfig"

net/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ obj-$(CONFIG_ATM) += atm/
4242
obj-$(CONFIG_DECNET) += decnet/
4343
obj-$(CONFIG_ECONET) += econet/
4444
obj-$(CONFIG_VLAN_8021Q) += 8021q/
45+
obj-$(CONFIG_IP_DCCP) += dccp/
4546
obj-$(CONFIG_IP_SCTP) += sctp/
4647

4748
ifeq ($(CONFIG_NET),y)

net/dccp/Kconfig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
menu "DCCP Configuration (EXPERIMENTAL)"
2+
depends on INET && EXPERIMENTAL
3+
4+
config IP_DCCP
5+
tristate "The DCCP Protocol (EXPERIMENTAL)"
6+
---help---
7+
Datagram Congestion Control Protocol
8+
9+
From draft-ietf-dccp-spec-11 <http://www.icir.org/kohler/dcp/draft-ietf-dccp-spec-11.txt>.
10+
11+
The Datagram Congestion Control Protocol (DCCP) is a transport
12+
protocol that implements bidirectional, unicast connections of
13+
congestion-controlled, unreliable datagrams. It should be suitable
14+
for use by applications such as streaming media, Internet telephony,
15+
and on-line games
16+
17+
To compile this protocol support as a module, choose M here: the
18+
module will be called dccp.
19+
20+
If in doubt, say N.
21+
22+
source "net/dccp/ccids/Kconfig"
23+
24+
endmenu

net/dccp/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
obj-$(CONFIG_IP_DCCP) += dccp.o
2+
3+
dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o timer.o
4+
5+
obj-y += ccids/

net/dccp/ccid.c

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* net/dccp/ccid.c
3+
*
4+
* An implementation of the DCCP protocol
5+
* Arnaldo Carvalho de Melo <[email protected]>
6+
*
7+
* CCID infrastructure
8+
*
9+
* This program is free software; you can redistribute it and/or modify it
10+
* under the terms of the GNU General Public License version 2 as
11+
* published by the Free Software Foundation.
12+
*/
13+
14+
#include "ccid.h"
15+
16+
static struct ccid *ccids[CCID_MAX];
17+
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
18+
static atomic_t ccids_lockct = ATOMIC_INIT(0);
19+
static DEFINE_SPINLOCK(ccids_lock);
20+
21+
/*
22+
* The strategy is: modifications ccids vector are short, do not sleep and
23+
* veeery rare, but read access should be free of any exclusive locks.
24+
*/
25+
static void ccids_write_lock(void)
26+
{
27+
spin_lock(&ccids_lock);
28+
while (atomic_read(&ccids_lockct) != 0) {
29+
spin_unlock(&ccids_lock);
30+
yield();
31+
spin_lock(&ccids_lock);
32+
}
33+
}
34+
35+
static inline void ccids_write_unlock(void)
36+
{
37+
spin_unlock(&ccids_lock);
38+
}
39+
40+
static inline void ccids_read_lock(void)
41+
{
42+
atomic_inc(&ccids_lockct);
43+
spin_unlock_wait(&ccids_lock);
44+
}
45+
46+
static inline void ccids_read_unlock(void)
47+
{
48+
atomic_dec(&ccids_lockct);
49+
}
50+
51+
#else
52+
#define ccids_write_lock() do { } while(0)
53+
#define ccids_write_unlock() do { } while(0)
54+
#define ccids_read_lock() do { } while(0)
55+
#define ccids_read_unlock() do { } while(0)
56+
#endif
57+
58+
int ccid_register(struct ccid *ccid)
59+
{
60+
int err;
61+
62+
if (ccid->ccid_init == NULL)
63+
return -1;
64+
65+
ccids_write_lock();
66+
err = -EEXIST;
67+
if (ccids[ccid->ccid_id] == NULL) {
68+
ccids[ccid->ccid_id] = ccid;
69+
err = 0;
70+
}
71+
ccids_write_unlock();
72+
if (err == 0)
73+
pr_info("CCID: Registered CCID %d (%s)\n",
74+
ccid->ccid_id, ccid->ccid_name);
75+
return err;
76+
}
77+
78+
EXPORT_SYMBOL_GPL(ccid_register);
79+
80+
int ccid_unregister(struct ccid *ccid)
81+
{
82+
ccids_write_lock();
83+
ccids[ccid->ccid_id] = NULL;
84+
ccids_write_unlock();
85+
pr_info("CCID: Unregistered CCID %d (%s)\n",
86+
ccid->ccid_id, ccid->ccid_name);
87+
return 0;
88+
}
89+
90+
EXPORT_SYMBOL_GPL(ccid_unregister);
91+
92+
struct ccid *ccid_init(unsigned char id, struct sock *sk)
93+
{
94+
struct ccid *ccid;
95+
96+
#ifdef CONFIG_KMOD
97+
if (ccids[id] == NULL)
98+
request_module("net-dccp-ccid-%d", id);
99+
#endif
100+
ccids_read_lock();
101+
102+
ccid = ccids[id];
103+
if (ccid == NULL)
104+
goto out;
105+
106+
if (!try_module_get(ccid->ccid_owner))
107+
goto out_err;
108+
109+
if (ccid->ccid_init(sk) != 0)
110+
goto out_module_put;
111+
out:
112+
ccids_read_unlock();
113+
return ccid;
114+
out_module_put:
115+
module_put(ccid->ccid_owner);
116+
out_err:
117+
ccid = NULL;
118+
goto out;
119+
}
120+
121+
EXPORT_SYMBOL_GPL(ccid_init);
122+
123+
void ccid_exit(struct ccid *ccid, struct sock *sk)
124+
{
125+
if (ccid == NULL)
126+
return;
127+
128+
ccids_read_lock();
129+
130+
if (ccids[ccid->ccid_id] != NULL) {
131+
if (ccid->ccid_exit != NULL)
132+
ccid->ccid_exit(sk);
133+
module_put(ccid->ccid_owner);
134+
}
135+
136+
ccids_read_unlock();
137+
}
138+
139+
EXPORT_SYMBOL_GPL(ccid_exit);

net/dccp/ccid.h

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#ifndef _CCID_H
2+
#define _CCID_H
3+
/*
4+
* net/dccp/ccid.h
5+
*
6+
* An implementation of the DCCP protocol
7+
* Arnaldo Carvalho de Melo <[email protected]>
8+
*
9+
* CCID infrastructure
10+
*
11+
* This program is free software; you can redistribute it and/or modify it
12+
* under the terms of the GNU General Public License version 2 as
13+
* published by the Free Software Foundation.
14+
*/
15+
16+
#include <net/sock.h>
17+
#include <linux/dccp.h>
18+
#include <linux/list.h>
19+
#include <linux/module.h>
20+
21+
#define CCID_MAX 255
22+
23+
struct ccid {
24+
unsigned char ccid_id;
25+
const char *ccid_name;
26+
struct module *ccid_owner;
27+
int (*ccid_init)(struct sock *sk);
28+
void (*ccid_exit)(struct sock *sk);
29+
int (*ccid_hc_rx_init)(struct sock *sk);
30+
int (*ccid_hc_tx_init)(struct sock *sk);
31+
void (*ccid_hc_rx_exit)(struct sock *sk);
32+
void (*ccid_hc_tx_exit)(struct sock *sk);
33+
void (*ccid_hc_rx_packet_recv)(struct sock *sk, struct sk_buff *skb);
34+
int (*ccid_hc_rx_parse_options)(struct sock *sk,
35+
unsigned char option,
36+
unsigned char len, u16 idx,
37+
unsigned char* value);
38+
void (*ccid_hc_rx_insert_options)(struct sock *sk, struct sk_buff *skb);
39+
void (*ccid_hc_tx_insert_options)(struct sock *sk, struct sk_buff *skb);
40+
void (*ccid_hc_tx_packet_recv)(struct sock *sk, struct sk_buff *skb);
41+
int (*ccid_hc_tx_parse_options)(struct sock *sk,
42+
unsigned char option,
43+
unsigned char len, u16 idx,
44+
unsigned char* value);
45+
int (*ccid_hc_tx_send_packet)(struct sock *sk,
46+
struct sk_buff *skb, int len,
47+
long *delay);
48+
void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, int len);
49+
};
50+
51+
extern int ccid_register(struct ccid *ccid);
52+
extern int ccid_unregister(struct ccid *ccid);
53+
54+
extern struct ccid *ccid_init(unsigned char id, struct sock *sk);
55+
extern void ccid_exit(struct ccid *ccid, struct sock *sk);
56+
57+
static inline void __ccid_get(struct ccid *ccid)
58+
{
59+
__module_get(ccid->ccid_owner);
60+
}
61+
62+
static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
63+
struct sk_buff *skb, int len,
64+
long *delay)
65+
{
66+
int rc = 0;
67+
if (ccid->ccid_hc_tx_send_packet != NULL)
68+
rc = ccid->ccid_hc_tx_send_packet(sk, skb, len, delay);
69+
return rc;
70+
}
71+
72+
static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
73+
int more, int len)
74+
{
75+
if (ccid->ccid_hc_tx_packet_sent != NULL)
76+
ccid->ccid_hc_tx_packet_sent(sk, more, len);
77+
}
78+
79+
static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk)
80+
{
81+
int rc = 0;
82+
if (ccid->ccid_hc_rx_init != NULL)
83+
rc = ccid->ccid_hc_rx_init(sk);
84+
return rc;
85+
}
86+
87+
static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
88+
{
89+
int rc = 0;
90+
if (ccid->ccid_hc_tx_init != NULL)
91+
rc = ccid->ccid_hc_tx_init(sk);
92+
return rc;
93+
}
94+
95+
static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
96+
{
97+
if (ccid->ccid_hc_rx_exit != NULL)
98+
ccid->ccid_hc_rx_exit(sk);
99+
}
100+
101+
static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
102+
{
103+
if (ccid->ccid_hc_tx_exit != NULL)
104+
ccid->ccid_hc_tx_exit(sk);
105+
}
106+
107+
static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
108+
struct sk_buff *skb)
109+
{
110+
if (ccid->ccid_hc_rx_packet_recv != NULL)
111+
ccid->ccid_hc_rx_packet_recv(sk, skb);
112+
}
113+
114+
static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
115+
struct sk_buff *skb)
116+
{
117+
if (ccid->ccid_hc_tx_packet_recv != NULL)
118+
ccid->ccid_hc_tx_packet_recv(sk, skb);
119+
}
120+
121+
static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
122+
unsigned char option,
123+
unsigned char len, u16 idx,
124+
unsigned char* value)
125+
{
126+
int rc = 0;
127+
if (ccid->ccid_hc_tx_parse_options != NULL)
128+
rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx, value);
129+
return rc;
130+
}
131+
132+
static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
133+
unsigned char option,
134+
unsigned char len, u16 idx,
135+
unsigned char* value)
136+
{
137+
int rc = 0;
138+
if (ccid->ccid_hc_rx_parse_options != NULL)
139+
rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value);
140+
return rc;
141+
}
142+
143+
static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
144+
struct sk_buff *skb)
145+
{
146+
if (ccid->ccid_hc_tx_insert_options != NULL)
147+
ccid->ccid_hc_tx_insert_options(sk, skb);
148+
}
149+
150+
static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
151+
struct sk_buff *skb)
152+
{
153+
if (ccid->ccid_hc_rx_insert_options != NULL)
154+
ccid->ccid_hc_rx_insert_options(sk, skb);
155+
}
156+
#endif /* _CCID_H */

net/dccp/ccids/Kconfig

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
menu "DCCP CCIDs Configuration (EXPERIMENTAL)"
2+
depends on IP_DCCP && EXPERIMENTAL
3+
4+
config IP_DCCP_CCID3
5+
tristate "CCID3 (TFRC) (EXPERIMENTAL)"
6+
depends on IP_DCCP
7+
---help---
8+
CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
9+
rate-controlled congestion control mechanism. TFRC is designed to
10+
be reasonably fair when competing for bandwidth with TCP-like flows,
11+
where a flow is "reasonably fair" if its sending rate is generally
12+
within a factor of two of the sending rate of a TCP flow under the
13+
same conditions. However, TFRC has a much lower variation of
14+
throughput over time compared with TCP, which makes CCID 3 more
15+
suitable than CCID 2 for applications such streaming media where a
16+
relatively smooth sending rate is of importance.
17+
18+
CCID 3 is further described in [CCID 3 PROFILE]. The TFRC
19+
congestion control algorithms were initially described in RFC 3448.
20+
21+
This text was extracted from draft-ietf-dccp-spec-11.txt.
22+
23+
If in doubt, say M.
24+
25+
endmenu

net/dccp/ccids/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o
2+
3+
dccp_ccid3-y := ccid3.o

0 commit comments

Comments
 (0)