Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/um/drivers/umcast_kern.c
10817 views
1
/*
2
* user-mode-linux networking multicast transport
3
* Copyright (C) 2001 by Harald Welte <[email protected]>
4
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
5
*
6
* based on the existing uml-networking code, which is
7
* Copyright (C) 2001 Lennert Buytenhek ([email protected]) and
8
* James Leu ([email protected]).
9
* Copyright (C) 2001 by various other people who didn't put their name here.
10
*
11
* Licensed under the GPL.
12
*/
13
14
#include "linux/init.h"
15
#include <linux/netdevice.h>
16
#include "umcast.h"
17
#include "net_kern.h"
18
19
struct umcast_init {
20
char *addr;
21
int lport;
22
int rport;
23
int ttl;
24
bool unicast;
25
};
26
27
static void umcast_init(struct net_device *dev, void *data)
28
{
29
struct uml_net_private *pri;
30
struct umcast_data *dpri;
31
struct umcast_init *init = data;
32
33
pri = netdev_priv(dev);
34
dpri = (struct umcast_data *) pri->user;
35
dpri->addr = init->addr;
36
dpri->lport = init->lport;
37
dpri->rport = init->rport;
38
dpri->unicast = init->unicast;
39
dpri->ttl = init->ttl;
40
dpri->dev = dev;
41
42
if (dpri->unicast) {
43
printk(KERN_INFO "ucast backend address: %s:%u listen port: "
44
"%u\n", dpri->addr, dpri->rport, dpri->lport);
45
} else {
46
printk(KERN_INFO "mcast backend multicast address: %s:%u, "
47
"TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl);
48
}
49
}
50
51
static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
52
{
53
return net_recvfrom(fd, skb_mac_header(skb),
54
skb->dev->mtu + ETH_HEADER_OTHER);
55
}
56
57
static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
58
{
59
return umcast_user_write(fd, skb->data, skb->len,
60
(struct umcast_data *) &lp->user);
61
}
62
63
static const struct net_kern_info umcast_kern_info = {
64
.init = umcast_init,
65
.protocol = eth_protocol,
66
.read = umcast_read,
67
.write = umcast_write,
68
};
69
70
static int mcast_setup(char *str, char **mac_out, void *data)
71
{
72
struct umcast_init *init = data;
73
char *port_str = NULL, *ttl_str = NULL, *remain;
74
char *last;
75
76
*init = ((struct umcast_init)
77
{ .addr = "239.192.168.1",
78
.lport = 1102,
79
.ttl = 1 });
80
81
remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
82
NULL);
83
if (remain != NULL) {
84
printk(KERN_ERR "mcast_setup - Extra garbage on "
85
"specification : '%s'\n", remain);
86
return 0;
87
}
88
89
if (port_str != NULL) {
90
init->lport = simple_strtoul(port_str, &last, 10);
91
if ((*last != '\0') || (last == port_str)) {
92
printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
93
port_str);
94
return 0;
95
}
96
}
97
98
if (ttl_str != NULL) {
99
init->ttl = simple_strtoul(ttl_str, &last, 10);
100
if ((*last != '\0') || (last == ttl_str)) {
101
printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
102
ttl_str);
103
return 0;
104
}
105
}
106
107
init->unicast = false;
108
init->rport = init->lport;
109
110
printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
111
init->lport, init->ttl);
112
113
return 1;
114
}
115
116
static int ucast_setup(char *str, char **mac_out, void *data)
117
{
118
struct umcast_init *init = data;
119
char *lport_str = NULL, *rport_str = NULL, *remain;
120
char *last;
121
122
*init = ((struct umcast_init)
123
{ .addr = "",
124
.lport = 1102,
125
.rport = 1102 });
126
127
remain = split_if_spec(str, mac_out, &init->addr,
128
&lport_str, &rport_str, NULL);
129
if (remain != NULL) {
130
printk(KERN_ERR "ucast_setup - Extra garbage on "
131
"specification : '%s'\n", remain);
132
return 0;
133
}
134
135
if (lport_str != NULL) {
136
init->lport = simple_strtoul(lport_str, &last, 10);
137
if ((*last != '\0') || (last == lport_str)) {
138
printk(KERN_ERR "ucast_setup - Bad listen port : "
139
"'%s'\n", lport_str);
140
return 0;
141
}
142
}
143
144
if (rport_str != NULL) {
145
init->rport = simple_strtoul(rport_str, &last, 10);
146
if ((*last != '\0') || (last == rport_str)) {
147
printk(KERN_ERR "ucast_setup - Bad remote port : "
148
"'%s'\n", rport_str);
149
return 0;
150
}
151
}
152
153
init->unicast = true;
154
155
printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n",
156
init->lport, init->addr, init->rport);
157
158
return 1;
159
}
160
161
static struct transport mcast_transport = {
162
.list = LIST_HEAD_INIT(mcast_transport.list),
163
.name = "mcast",
164
.setup = mcast_setup,
165
.user = &umcast_user_info,
166
.kern = &umcast_kern_info,
167
.private_size = sizeof(struct umcast_data),
168
.setup_size = sizeof(struct umcast_init),
169
};
170
171
static struct transport ucast_transport = {
172
.list = LIST_HEAD_INIT(ucast_transport.list),
173
.name = "ucast",
174
.setup = ucast_setup,
175
.user = &umcast_user_info,
176
.kern = &umcast_kern_info,
177
.private_size = sizeof(struct umcast_data),
178
.setup_size = sizeof(struct umcast_init),
179
};
180
181
static int register_umcast(void)
182
{
183
register_transport(&mcast_transport);
184
register_transport(&ucast_transport);
185
return 0;
186
}
187
188
late_initcall(register_umcast);
189
190