Skip to content

Commit b79fcee

Browse files
committed
Add IPv6 support to the kernel module.
This adds IPv6 support to the kernel module side. Signed-off-by: Auke Kok <auke.kok@versity.com>
1 parent 41e3cb3 commit b79fcee

10 files changed

Lines changed: 208 additions & 124 deletions

File tree

kmod/src/client.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ static void scoutfs_client_connect_worker(struct work_struct *work)
479479
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
480480
struct scoutfs_mount_options opts;
481481
struct scoutfs_net_greeting greet;
482-
struct sockaddr_in sin;
482+
struct sockaddr_storage sin;
483483
bool am_quorum;
484484
int ret;
485485

kmod/src/fence.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "sysfs.h"
2626
#include "server.h"
2727
#include "fence.h"
28+
#include "net.h"
2829

2930
/*
3031
* Fencing ensures that a given mount can no longer write to the
@@ -79,7 +80,7 @@ struct pending_fence {
7980
struct timer_list timer;
8081

8182
ktime_t start_kt;
82-
__be32 ipv4_addr;
83+
union scoutfs_inet_addr addr;
8384
bool fenced;
8485
bool error;
8586
int reason;
@@ -171,14 +172,19 @@ static ssize_t error_store(struct kobject *kobj, struct kobj_attribute *attr, co
171172
}
172173
SCOUTFS_ATTR_RW(error);
173174

174-
static ssize_t ipv4_addr_show(struct kobject *kobj,
175+
static ssize_t inet_addr_show(struct kobject *kobj,
175176
struct kobj_attribute *attr, char *buf)
176177
{
177178
DECLARE_FENCE_FROM_KOBJ(fence, kobj);
179+
struct sockaddr_storage sin;
178180

179-
return snprintf(buf, PAGE_SIZE, "%pI4", &fence->ipv4_addr);
181+
memset(&sin, 0, sizeof(struct sockaddr_storage));
182+
183+
scoutfs_addr_to_sin(&sin, &fence->addr);
184+
185+
return snprintf(buf, PAGE_SIZE, "%pISc", SIN_ARG(&sin));
180186
}
181-
SCOUTFS_ATTR_RO(ipv4_addr);
187+
SCOUTFS_ATTR_RO(inet_addr);
182188

183189
static ssize_t reason_show(struct kobject *kobj, struct kobj_attribute *attr,
184190
char *buf)
@@ -212,7 +218,7 @@ static struct attribute *fence_attrs[] = {
212218
SCOUTFS_ATTR_PTR(elapsed_secs),
213219
SCOUTFS_ATTR_PTR(fenced),
214220
SCOUTFS_ATTR_PTR(error),
215-
SCOUTFS_ATTR_PTR(ipv4_addr),
221+
SCOUTFS_ATTR_PTR(inet_addr),
216222
SCOUTFS_ATTR_PTR(reason),
217223
SCOUTFS_ATTR_PTR(rid),
218224
NULL,
@@ -232,7 +238,7 @@ static void fence_timeout(struct timer_list *timer)
232238
wake_up(&fi->waitq);
233239
}
234240

235-
int scoutfs_fence_start(struct super_block *sb, u64 rid, __be32 ipv4_addr, int reason)
241+
int scoutfs_fence_start(struct super_block *sb, u64 rid, union scoutfs_inet_addr *addr, int reason)
236242
{
237243
DECLARE_FENCE_INFO(sb, fi);
238244
struct pending_fence *fence;
@@ -248,7 +254,7 @@ int scoutfs_fence_start(struct super_block *sb, u64 rid, __be32 ipv4_addr, int r
248254
scoutfs_sysfs_init_attrs(sb, &fence->ssa);
249255

250256
fence->start_kt = ktime_get();
251-
fence->ipv4_addr = ipv4_addr;
257+
memcpy(&fence->addr, addr, sizeof(union scoutfs_inet_addr));
252258
fence->fenced = false;
253259
fence->error = false;
254260
fence->reason = reason;

kmod/src/fence.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ enum {
77
SCOUTFS_FENCE_QUORUM_BLOCK_LEADER,
88
};
99

10-
int scoutfs_fence_start(struct super_block *sb, u64 rid, __be32 ipv4_addr, int reason);
10+
int scoutfs_fence_start(struct super_block *sb, u64 rid, union scoutfs_inet_addr *addr, int reason);
1111
int scoutfs_fence_next(struct super_block *sb, u64 *rid, int *reason, bool *error);
1212
int scoutfs_fence_reason_pending(struct super_block *sb, int reason);
1313
int scoutfs_fence_free(struct super_block *sb, u64 rid);

kmod/src/net.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,8 @@ static void scoutfs_net_connect_worker(struct work_struct *work)
11631163

11641164
trace_scoutfs_net_connect_work_enter(sb, 0, 0);
11651165

1166-
ret = kc_sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
1166+
ret = kc_sock_create_kern(conn->connect_sin.ss_family,
1167+
SOCK_STREAM, IPPROTO_TCP, &sock);
11671168
if (ret)
11681169
goto out;
11691170

@@ -1184,7 +1185,9 @@ static void scoutfs_net_connect_worker(struct work_struct *work)
11841185
trace_scoutfs_conn_connect_start(conn);
11851186

11861187
ret = kernel_connect(sock, (struct sockaddr *)&conn->connect_sin,
1187-
sizeof(struct sockaddr_in), 0);
1188+
conn->connect_sin.ss_family == AF_INET ?
1189+
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
1190+
0);
11881191
if (ret)
11891192
goto out;
11901193

@@ -1226,6 +1229,13 @@ static bool empty_accepted_list(struct scoutfs_net_connection *conn)
12261229
return empty;
12271230
}
12281231

1232+
/*
1233+
* sockaddr_storage wraps both _in and _in6, which have _port always
1234+
* __be16 at the same offset, and we only need to test whether it's
1235+
* zero.
1236+
*/
1237+
#define sockaddr_port_is_nonzero(sin) ((sin).__data[0] || (sin).__data[1])
1238+
12291239
/*
12301240
* Safely shut down an active connection. This can be triggered by
12311241
* errors in workers or by an external call to free the connection. The
@@ -1249,7 +1259,7 @@ static void scoutfs_net_shutdown_worker(struct work_struct *work)
12491259
trace_scoutfs_conn_shutdown_start(conn);
12501260

12511261
/* connected and accepted conns print a message */
1252-
if (conn->peername.sin_port != 0)
1262+
if (sockaddr_port_is_nonzero(conn->peername))
12531263
scoutfs_info(sb, "%s "SIN_FMT" -> "SIN_FMT,
12541264
conn->listening_conn ? "server closing" :
12551265
"client disconnected",
@@ -1379,6 +1389,7 @@ static void scoutfs_net_reconn_free_worker(struct work_struct *work)
13791389
DEFINE_CONN_FROM_WORK(conn, work, reconn_free_dwork.work);
13801390
struct super_block *sb = conn->sb;
13811391
struct scoutfs_net_connection *acc;
1392+
union scoutfs_inet_addr addr;
13821393
unsigned long now = jiffies;
13831394
unsigned long deadline = 0;
13841395
bool requeue = false;
@@ -1399,8 +1410,9 @@ static void scoutfs_net_reconn_free_worker(struct work_struct *work)
13991410
if (!test_conn_fl(conn, shutting_down)) {
14001411
scoutfs_info(sb, "client "SIN_FMT" reconnect timed out, fencing",
14011412
SIN_ARG(&acc->last_peername));
1413+
scoutfs_sin_to_addr(&addr, &acc->last_peername);
14021414
ret = scoutfs_fence_start(sb, acc->rid,
1403-
acc->last_peername.sin_addr.s_addr,
1415+
&addr,
14041416
SCOUTFS_FENCE_CLIENT_RECONNECT);
14051417
if (ret) {
14061418
scoutfs_err(sb, "client fence returned err %d, shutting down server",
@@ -1483,9 +1495,9 @@ scoutfs_net_alloc_conn(struct super_block *sb,
14831495
conn->req_funcs = req_funcs;
14841496
spin_lock_init(&conn->lock);
14851497
init_waitqueue_head(&conn->waitq);
1486-
conn->sockname.sin_family = AF_INET;
1487-
conn->peername.sin_family = AF_INET;
1488-
conn->last_peername.sin_family = AF_INET;
1498+
conn->sockname.ss_family = AF_UNSPEC;
1499+
conn->peername.ss_family = AF_UNSPEC;
1500+
conn->last_peername.ss_family = AF_UNSPEC;
14891501
INIT_LIST_HEAD(&conn->accepted_head);
14901502
INIT_LIST_HEAD(&conn->accepted_list);
14911503
conn->next_send_seq = 1;
@@ -1562,7 +1574,7 @@ void scoutfs_net_free_conn(struct super_block *sb,
15621574
*/
15631575
int scoutfs_net_bind(struct super_block *sb,
15641576
struct scoutfs_net_connection *conn,
1565-
struct sockaddr_in *sin)
1577+
struct sockaddr_storage *sin)
15661578
{
15671579
struct socket *sock = NULL;
15681580
int addrlen;
@@ -1573,7 +1585,7 @@ int scoutfs_net_bind(struct super_block *sb,
15731585
if (WARN_ON_ONCE(conn->sock))
15741586
return -EINVAL;
15751587

1576-
ret = kc_sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
1588+
ret = kc_sock_create_kern(sin->ss_family, SOCK_STREAM, IPPROTO_TCP, &sock);
15771589
if (ret)
15781590
goto out;
15791591

@@ -1585,7 +1597,7 @@ int scoutfs_net_bind(struct super_block *sb,
15851597
if (ret)
15861598
goto out;
15871599

1588-
addrlen = sizeof(struct sockaddr_in);
1600+
addrlen = sin->ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
15891601
ret = kernel_bind(sock, (struct sockaddr *)sin, addrlen);
15901602
if (ret)
15911603
goto out;
@@ -1601,7 +1613,7 @@ int scoutfs_net_bind(struct super_block *sb,
16011613
ret = 0;
16021614

16031615
conn->sock = sock;
1604-
*sin = conn->sockname;
1616+
sin = (struct sockaddr_storage *)&conn->sockname;
16051617

16061618
out:
16071619
if (ret < 0 && sock)
@@ -1636,7 +1648,7 @@ static bool connect_result(struct scoutfs_net_connection *conn, int *error)
16361648
done = true;
16371649
*error = 0;
16381650
} else if (test_conn_fl(conn, shutting_down) ||
1639-
conn->connect_sin.sin_family == 0) {
1651+
conn->connect_sin.ss_family == AF_UNSPEC) {
16401652
done = true;
16411653
*error = -ESHUTDOWN;
16421654
}
@@ -1657,7 +1669,7 @@ static bool connect_result(struct scoutfs_net_connection *conn, int *error)
16571669
*/
16581670
int scoutfs_net_connect(struct super_block *sb,
16591671
struct scoutfs_net_connection *conn,
1660-
struct sockaddr_in *sin, unsigned long timeout_ms)
1672+
struct sockaddr_storage *sin, unsigned long timeout_ms)
16611673
{
16621674
int ret = 0;
16631675

kmod/src/net.h

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ struct scoutfs_net_connection {
4949
unsigned long flags; /* CONN_FL_* bitmask */
5050
unsigned long reconn_deadline;
5151

52-
struct sockaddr_in connect_sin;
52+
struct sockaddr_storage connect_sin;
5353
unsigned long connect_timeout_ms;
5454

5555
struct socket *sock;
5656
u64 rid;
5757
u64 greeting_id;
58-
struct sockaddr_in sockname;
59-
struct sockaddr_in peername;
60-
struct sockaddr_in last_peername;
58+
struct sockaddr_storage sockname;
59+
struct sockaddr_storage peername;
60+
struct sockaddr_storage last_peername;
6161

6262
struct list_head accepted_head;
6363
struct scoutfs_net_connection *listening_conn;
@@ -97,27 +97,44 @@ enum conn_flags {
9797
CONN_FL_reconn_freeing = (1UL << 6), /* waiting done, setter frees */
9898
};
9999

100-
#define SIN_FMT "%pIS:%u"
101-
#define SIN_ARG(sin) sin, be16_to_cpu((sin)->sin_port)
100+
#define SIN_FMT "%pISpc"
101+
#define SIN_ARG(sin) sin
102102

103-
static inline void scoutfs_addr_to_sin(struct sockaddr_in *sin,
103+
static inline void scoutfs_addr_to_sin(struct sockaddr_storage *sin,
104104
union scoutfs_inet_addr *addr)
105105
{
106-
BUG_ON(addr->v4.family != cpu_to_le16(SCOUTFS_AF_IPV4));
107-
108-
sin->sin_family = AF_INET;
109-
sin->sin_addr.s_addr = cpu_to_be32(le32_to_cpu(addr->v4.addr));
110-
sin->sin_port = cpu_to_be16(le16_to_cpu(addr->v4.port));
106+
if (addr->v4.family == cpu_to_le16(SCOUTFS_AF_IPV4)) {
107+
struct sockaddr_in *sin4 = (struct sockaddr_in *)sin;
108+
memset(sin, 0, sizeof(struct sockaddr_storage));
109+
sin4->sin_family = AF_INET;
110+
sin4->sin_addr.s_addr = cpu_to_be32(le32_to_cpu(addr->v4.addr));
111+
sin4->sin_port = cpu_to_be16(le16_to_cpu(addr->v4.port));
112+
} else if (addr->v6.family == cpu_to_le16(SCOUTFS_AF_IPV6)) {
113+
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
114+
memset(sin, 0, sizeof(struct sockaddr_storage));
115+
sin6->sin6_family = AF_INET6;
116+
memcpy(&sin6->sin6_addr.in6_u.u6_addr8, &addr->v6.addr, 16);
117+
sin6->sin6_port = cpu_to_be16(le16_to_cpu(addr->v6.port));
118+
} else
119+
BUG();
111120
}
112121

113-
static inline void scoutfs_sin_to_addr(union scoutfs_inet_addr *addr, struct sockaddr_in *sin)
122+
static inline void scoutfs_sin_to_addr(union scoutfs_inet_addr *addr, struct sockaddr_storage *sin)
114123
{
115-
BUG_ON(sin->sin_family != AF_INET);
116-
117-
memset(addr, 0, sizeof(union scoutfs_inet_addr));
118-
addr->v4.family = cpu_to_le16(SCOUTFS_AF_IPV4);
119-
addr->v4.addr = be32_to_le32(sin->sin_addr.s_addr);
120-
addr->v4.port = be16_to_le16(sin->sin_port);
124+
if (sin->ss_family == AF_INET) {
125+
struct sockaddr_in *sin4 = (struct sockaddr_in *)sin;
126+
memset(addr, 0, sizeof(union scoutfs_inet_addr));
127+
addr->v4.family = cpu_to_le16(SCOUTFS_AF_IPV4);
128+
addr->v4.addr = be32_to_le32(sin4->sin_addr.s_addr);
129+
addr->v4.port = be16_to_le16(sin4->sin_port);
130+
} else if (sin->ss_family == AF_INET6) {
131+
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
132+
memset(addr, 0, sizeof(union scoutfs_inet_addr));
133+
addr->v6.family = cpu_to_le16(SCOUTFS_AF_IPV6);
134+
memcpy(&addr->v6.addr, &sin6->sin6_addr.in6_u.u6_addr8, 16);
135+
addr->v6.port = be16_to_le16(sin6->sin6_port);
136+
} else
137+
BUG();
121138
}
122139

123140
struct scoutfs_net_connection *
@@ -128,10 +145,10 @@ scoutfs_net_alloc_conn(struct super_block *sb,
128145
u64 scoutfs_net_client_rid(struct scoutfs_net_connection *conn);
129146
int scoutfs_net_connect(struct super_block *sb,
130147
struct scoutfs_net_connection *conn,
131-
struct sockaddr_in *sin, unsigned long timeout_ms);
148+
struct sockaddr_storage *sin, unsigned long timeout_ms);
132149
int scoutfs_net_bind(struct super_block *sb,
133150
struct scoutfs_net_connection *conn,
134-
struct sockaddr_in *sin);
151+
struct sockaddr_storage *sin);
135152
void scoutfs_net_listen(struct super_block *sb,
136153
struct scoutfs_net_connection *conn);
137154
int scoutfs_net_submit_request(struct super_block *sb,

0 commit comments

Comments
 (0)