Skip to content

Commit

Permalink
[DCCP]: Initial implementation
Browse files Browse the repository at this point in the history
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 <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Arnaldo Carvalho de Melo authored and David S. Miller committed Aug 29, 2005
1 parent c4365c9 commit 7c65787
Show file tree
Hide file tree
Showing 22 changed files with 7,746 additions and 0 deletions.
432 changes: 432 additions & 0 deletions include/linux/dccp.h

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions include/linux/in.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum {
IPPROTO_PUP = 12, /* PUP protocol */
IPPROTO_UDP = 17, /* User Datagram Protocol */
IPPROTO_IDP = 22, /* XNS IDP protocol */
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */
IPPROTO_RSVP = 46, /* RSVP protocol */
IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */

Expand Down
1 change: 1 addition & 0 deletions include/linux/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum sock_type {
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
SOCK_DCCP = 6,
SOCK_PACKET = 10,
};

Expand Down
1 change: 1 addition & 0 deletions include/linux/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ struct ucred {
#define SOL_IRDA 266
#define SOL_NETBEUI 267
#define SOL_LLC 268
#define SOL_DCCP 269

/* IPX options */
#define IPX_TYPE 1
Expand Down
1 change: 1 addition & 0 deletions net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ source "net/bridge/netfilter/Kconfig"

endif

source "net/dccp/Kconfig"
source "net/sctp/Kconfig"
source "net/atm/Kconfig"
source "net/bridge/Kconfig"
Expand Down
1 change: 1 addition & 0 deletions net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_DECNET) += decnet/
obj-$(CONFIG_ECONET) += econet/
obj-$(CONFIG_VLAN_8021Q) += 8021q/
obj-$(CONFIG_IP_DCCP) += dccp/
obj-$(CONFIG_IP_SCTP) += sctp/

ifeq ($(CONFIG_NET),y)
Expand Down
24 changes: 24 additions & 0 deletions net/dccp/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
menu "DCCP Configuration (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL

config IP_DCCP
tristate "The DCCP Protocol (EXPERIMENTAL)"
---help---
Datagram Congestion Control Protocol

From draft-ietf-dccp-spec-11 <http://www.icir.org/kohler/dcp/draft-ietf-dccp-spec-11.txt>.

The Datagram Congestion Control Protocol (DCCP) is a transport
protocol that implements bidirectional, unicast connections of
congestion-controlled, unreliable datagrams. It should be suitable
for use by applications such as streaming media, Internet telephony,
and on-line games

To compile this protocol support as a module, choose M here: the
module will be called dccp.

If in doubt, say N.

source "net/dccp/ccids/Kconfig"

endmenu
5 changes: 5 additions & 0 deletions net/dccp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
obj-$(CONFIG_IP_DCCP) += dccp.o

dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o timer.o

obj-y += ccids/
139 changes: 139 additions & 0 deletions net/dccp/ccid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* net/dccp/ccid.c
*
* An implementation of the DCCP protocol
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* CCID infrastructure
*
* 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 "ccid.h"

static struct ccid *ccids[CCID_MAX];
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t ccids_lockct = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(ccids_lock);

/*
* The strategy is: modifications ccids vector are short, do not sleep and
* veeery rare, but read access should be free of any exclusive locks.
*/
static void ccids_write_lock(void)
{
spin_lock(&ccids_lock);
while (atomic_read(&ccids_lockct) != 0) {
spin_unlock(&ccids_lock);
yield();
spin_lock(&ccids_lock);
}
}

static inline void ccids_write_unlock(void)
{
spin_unlock(&ccids_lock);
}

static inline void ccids_read_lock(void)
{
atomic_inc(&ccids_lockct);
spin_unlock_wait(&ccids_lock);
}

static inline void ccids_read_unlock(void)
{
atomic_dec(&ccids_lockct);
}

#else
#define ccids_write_lock() do { } while(0)
#define ccids_write_unlock() do { } while(0)
#define ccids_read_lock() do { } while(0)
#define ccids_read_unlock() do { } while(0)
#endif

int ccid_register(struct ccid *ccid)
{
int err;

if (ccid->ccid_init == NULL)
return -1;

ccids_write_lock();
err = -EEXIST;
if (ccids[ccid->ccid_id] == NULL) {
ccids[ccid->ccid_id] = ccid;
err = 0;
}
ccids_write_unlock();
if (err == 0)
pr_info("CCID: Registered CCID %d (%s)\n",
ccid->ccid_id, ccid->ccid_name);
return err;
}

EXPORT_SYMBOL_GPL(ccid_register);

int ccid_unregister(struct ccid *ccid)
{
ccids_write_lock();
ccids[ccid->ccid_id] = NULL;
ccids_write_unlock();
pr_info("CCID: Unregistered CCID %d (%s)\n",
ccid->ccid_id, ccid->ccid_name);
return 0;
}

EXPORT_SYMBOL_GPL(ccid_unregister);

struct ccid *ccid_init(unsigned char id, struct sock *sk)
{
struct ccid *ccid;

#ifdef CONFIG_KMOD
if (ccids[id] == NULL)
request_module("net-dccp-ccid-%d", id);
#endif
ccids_read_lock();

ccid = ccids[id];
if (ccid == NULL)
goto out;

if (!try_module_get(ccid->ccid_owner))
goto out_err;

if (ccid->ccid_init(sk) != 0)
goto out_module_put;
out:
ccids_read_unlock();
return ccid;
out_module_put:
module_put(ccid->ccid_owner);
out_err:
ccid = NULL;
goto out;
}

EXPORT_SYMBOL_GPL(ccid_init);

void ccid_exit(struct ccid *ccid, struct sock *sk)
{
if (ccid == NULL)
return;

ccids_read_lock();

if (ccids[ccid->ccid_id] != NULL) {
if (ccid->ccid_exit != NULL)
ccid->ccid_exit(sk);
module_put(ccid->ccid_owner);
}

ccids_read_unlock();
}

EXPORT_SYMBOL_GPL(ccid_exit);
156 changes: 156 additions & 0 deletions net/dccp/ccid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#ifndef _CCID_H
#define _CCID_H
/*
* net/dccp/ccid.h
*
* An implementation of the DCCP protocol
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* CCID infrastructure
*
* 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 <net/sock.h>
#include <linux/dccp.h>
#include <linux/list.h>
#include <linux/module.h>

#define CCID_MAX 255

struct ccid {
unsigned char ccid_id;
const char *ccid_name;
struct module *ccid_owner;
int (*ccid_init)(struct sock *sk);
void (*ccid_exit)(struct sock *sk);
int (*ccid_hc_rx_init)(struct sock *sk);
int (*ccid_hc_tx_init)(struct sock *sk);
void (*ccid_hc_rx_exit)(struct sock *sk);
void (*ccid_hc_tx_exit)(struct sock *sk);
void (*ccid_hc_rx_packet_recv)(struct sock *sk, struct sk_buff *skb);
int (*ccid_hc_rx_parse_options)(struct sock *sk,
unsigned char option,
unsigned char len, u16 idx,
unsigned char* value);
void (*ccid_hc_rx_insert_options)(struct sock *sk, struct sk_buff *skb);
void (*ccid_hc_tx_insert_options)(struct sock *sk, struct sk_buff *skb);
void (*ccid_hc_tx_packet_recv)(struct sock *sk, struct sk_buff *skb);
int (*ccid_hc_tx_parse_options)(struct sock *sk,
unsigned char option,
unsigned char len, u16 idx,
unsigned char* value);
int (*ccid_hc_tx_send_packet)(struct sock *sk,
struct sk_buff *skb, int len,
long *delay);
void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, int len);
};

extern int ccid_register(struct ccid *ccid);
extern int ccid_unregister(struct ccid *ccid);

extern struct ccid *ccid_init(unsigned char id, struct sock *sk);
extern void ccid_exit(struct ccid *ccid, struct sock *sk);

static inline void __ccid_get(struct ccid *ccid)
{
__module_get(ccid->ccid_owner);
}

static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb, int len,
long *delay)
{
int rc = 0;
if (ccid->ccid_hc_tx_send_packet != NULL)
rc = ccid->ccid_hc_tx_send_packet(sk, skb, len, delay);
return rc;
}

static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
int more, int len)
{
if (ccid->ccid_hc_tx_packet_sent != NULL)
ccid->ccid_hc_tx_packet_sent(sk, more, len);
}

static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk)
{
int rc = 0;
if (ccid->ccid_hc_rx_init != NULL)
rc = ccid->ccid_hc_rx_init(sk);
return rc;
}

static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
int rc = 0;
if (ccid->ccid_hc_tx_init != NULL)
rc = ccid->ccid_hc_tx_init(sk);
return rc;
}

static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
{
if (ccid->ccid_hc_rx_exit != NULL)
ccid->ccid_hc_rx_exit(sk);
}

static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
{
if (ccid->ccid_hc_tx_exit != NULL)
ccid->ccid_hc_tx_exit(sk);
}

static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb)
{
if (ccid->ccid_hc_rx_packet_recv != NULL)
ccid->ccid_hc_rx_packet_recv(sk, skb);
}

static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb)
{
if (ccid->ccid_hc_tx_packet_recv != NULL)
ccid->ccid_hc_tx_packet_recv(sk, skb);
}

static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
unsigned char option,
unsigned char len, u16 idx,
unsigned char* value)
{
int rc = 0;
if (ccid->ccid_hc_tx_parse_options != NULL)
rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx, value);
return rc;
}

static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
unsigned char option,
unsigned char len, u16 idx,
unsigned char* value)
{
int rc = 0;
if (ccid->ccid_hc_rx_parse_options != NULL)
rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value);
return rc;
}

static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb)
{
if (ccid->ccid_hc_tx_insert_options != NULL)
ccid->ccid_hc_tx_insert_options(sk, skb);
}

static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb)
{
if (ccid->ccid_hc_rx_insert_options != NULL)
ccid->ccid_hc_rx_insert_options(sk, skb);
}
#endif /* _CCID_H */
25 changes: 25 additions & 0 deletions net/dccp/ccids/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
menu "DCCP CCIDs Configuration (EXPERIMENTAL)"
depends on IP_DCCP && EXPERIMENTAL

config IP_DCCP_CCID3
tristate "CCID3 (TFRC) (EXPERIMENTAL)"
depends on IP_DCCP
---help---
CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
rate-controlled congestion control mechanism. TFRC is designed to
be reasonably fair when competing for bandwidth with TCP-like flows,
where a flow is "reasonably fair" if its sending rate is generally
within a factor of two of the sending rate of a TCP flow under the
same conditions. However, TFRC has a much lower variation of
throughput over time compared with TCP, which makes CCID 3 more
suitable than CCID 2 for applications such streaming media where a
relatively smooth sending rate is of importance.

CCID 3 is further described in [CCID 3 PROFILE]. The TFRC
congestion control algorithms were initially described in RFC 3448.

This text was extracted from draft-ietf-dccp-spec-11.txt.

If in doubt, say M.

endmenu
3 changes: 3 additions & 0 deletions net/dccp/ccids/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o

dccp_ccid3-y := ccid3.o
Loading

0 comments on commit 7c65787

Please sign in to comment.