net/phonet/pep-gprs.c

Source file repositories/reference/linux-study-clean/net/phonet/pep-gprs.c

File Facts

System
Linux kernel
Corpus path
net/phonet/pep-gprs.c
Extension
.c
Size
6242 bytes
Lines
311
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops gprs_netdev_ops = {
	.ndo_open	= gprs_open,
	.ndo_stop	= gprs_close,
	.ndo_start_xmit	= gprs_xmit,
};

static void gprs_setup(struct net_device *dev)
{
	dev->features		= NETIF_F_FRAGLIST;
	dev->type		= ARPHRD_PHONET_PIPE;
	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
	dev->mtu		= GPRS_DEFAULT_MTU;
	dev->min_mtu		= 576;
	dev->max_mtu		= (PHONET_MAX_MTU - 11);
	dev->hard_header_len	= 0;
	dev->addr_len		= 0;
	dev->tx_queue_len	= 10;

	dev->netdev_ops		= &gprs_netdev_ops;
	dev->needs_free_netdev	= true;
}

/*
 * External interface
 */

/*
 * Attach a GPRS interface to a datagram socket.
 * Returns the interface index on success, negative error code on error.
 */
int gprs_attach(struct sock *sk)
{
	static const char ifname[] = "gprs%d";
	struct gprs_dev *gp;
	struct net_device *dev;
	int err;

	if (unlikely(sk->sk_type == SOCK_STREAM))
		return -EINVAL; /* need packet boundaries */

	/* Create net device */
	dev = alloc_netdev(sizeof(*gp), ifname, NET_NAME_UNKNOWN, gprs_setup);
	if (!dev)
		return -ENOMEM;
	gp = netdev_priv(dev);
	gp->sk = sk;
	gp->dev = dev;

	netif_stop_queue(dev);
	err = register_netdev(dev);
	if (err) {
		free_netdev(dev);
		return err;
	}

	lock_sock(sk);
	if (unlikely(sk->sk_user_data)) {
		err = -EBUSY;
		goto out_rel;
	}
	if (unlikely((1 << sk->sk_state & (TCPF_CLOSE|TCPF_LISTEN)) ||
			sock_flag(sk, SOCK_DEAD))) {
		err = -EINVAL;
		goto out_rel;
	}
	sk->sk_user_data	= gp;
	gp->old_state_change	= sk->sk_state_change;
	gp->old_data_ready	= sk->sk_data_ready;
	gp->old_write_space	= sk->sk_write_space;
	sk->sk_state_change	= gprs_state_change;
	sk->sk_data_ready	= gprs_data_ready;
	sk->sk_write_space	= gprs_write_space;
	release_sock(sk);
	sock_hold(sk);

	printk(KERN_DEBUG"%s: attached\n", dev->name);
	return dev->ifindex;

out_rel:
	release_sock(sk);
	unregister_netdev(dev);
	return err;
}

void gprs_detach(struct sock *sk)
{
	struct gprs_dev *gp = sk->sk_user_data;
	struct net_device *dev = gp->dev;

	lock_sock(sk);

Annotation

Implementation Notes