mirror of https://github.com/F-Stack/f-stack.git
IPv6: FreeBSD stack and f-stack support ipv6.
This commit is contained in:
parent
171a039c22
commit
d7140ab746
|
@ -107,6 +107,12 @@ net.inet.tcp.tcbhashsize=65536
|
|||
|
||||
kern.ncallout=262144
|
||||
|
||||
kern.features.inet6=1
|
||||
net.inet6.ip6.auto_linklocal=1
|
||||
net.inet6.ip6.accept_rtadv=2
|
||||
net.inet6.icmp6.rediraccept=1
|
||||
net.inet6.ip6.forwarding=0
|
||||
|
||||
[freebsd.sysctl]
|
||||
kern.ipc.somaxconn=32768
|
||||
kern.ipc.maxsockbuf=16777216
|
||||
|
|
|
@ -168,7 +168,7 @@ union sctpChunkOfInt {
|
|||
*/
|
||||
struct sctp_nat_msg {
|
||||
uint16_t msg; /**< one of the key messages defined above */
|
||||
#ifdef INET6
|
||||
#if INET6 && !FSTACK
|
||||
// struct ip6_hdr *ip_hdr; /**< pointer to ip packet header */ /*no inet6 support yet*/
|
||||
#else
|
||||
struct ip *ip_hdr; /**< pointer to ip packet header */
|
||||
|
|
|
@ -204,9 +204,14 @@ in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset)
|
|||
offset += m->m_pkthdr.csum_data; /* checksum offset */
|
||||
|
||||
if (offset + sizeof(u_short) > m->m_len) {
|
||||
#ifdef FSTACK
|
||||
printf("%s: delayed m_pullup, m->len: %d plen %u off %u "
|
||||
"csum_flags=%lu\n", __func__, m->m_len, plen, offset,
|
||||
m->m_pkthdr.csum_flags);
|
||||
#else
|
||||
"csum_flags=%b\n", __func__, m->m_len, plen, offset,
|
||||
(int)m->m_pkthdr.csum_flags, CSUM_BITS);
|
||||
#endif
|
||||
/*
|
||||
* XXX this should not happen, but if it does, the correct
|
||||
* behavior may be to insert the checksum in the appropriate
|
||||
|
|
52
lib/Makefile
52
lib/Makefile
|
@ -29,6 +29,7 @@ FF_KNI=1
|
|||
#FF_NETGRAPH=1
|
||||
#FF_IPFW=1
|
||||
#FF_USE_PAGE_ARRAY=1
|
||||
FF_INET6=1
|
||||
|
||||
|
||||
include ${TOPDIR}/mk/kern.pre.mk
|
||||
|
@ -87,6 +88,11 @@ ifdef FF_USE_PAGE_ARRAY
|
|||
HOST_CFLAGS+= -DFF_USE_PAGE_ARRAY
|
||||
endif
|
||||
|
||||
ifdef FF_INET6
|
||||
HOST_CFLAGS+= -DINET6
|
||||
CFLAGS+= -DINET6
|
||||
endif
|
||||
|
||||
HOST_C= ${CC} -c $(HOST_CFLAGS) ${HOST_INCLUDES} ${WERROR} ${PROF} $<
|
||||
|
||||
|
||||
|
@ -165,6 +171,9 @@ endif
|
|||
VPATH+= $S/netinet
|
||||
VPATH+= $S/netinet/libalias
|
||||
VPATH+= $S/netinet/cc
|
||||
ifdef FF_INET6
|
||||
VPATH+= $S/netinet6
|
||||
endif
|
||||
VPATH+= $S/netipsec
|
||||
ifdef FF_IPFW
|
||||
VPATH+= $S/netpfil/ipfw
|
||||
|
@ -442,6 +451,42 @@ NETINET_SRCS+= \
|
|||
alias_sctp.c \
|
||||
alias_util.c
|
||||
|
||||
ifdef FF_INET6
|
||||
NETINET6_SRCS+= \
|
||||
dest6.c \
|
||||
frag6.c \
|
||||
icmp6.c \
|
||||
in6.c \
|
||||
in6_ifattach.c \
|
||||
in6_mcast.c \
|
||||
in6_pcb.c \
|
||||
in6_pcbgroup.c \
|
||||
in6_proto.c \
|
||||
in6_rmx.c \
|
||||
in6_src.c \
|
||||
ip6_forward.c \
|
||||
ip6_id.c \
|
||||
ip6_input.c \
|
||||
ip6_mroute.c \
|
||||
ip6_output.c \
|
||||
mld6.c \
|
||||
nd6.c \
|
||||
nd6_nbr.c \
|
||||
nd6_rtr.c \
|
||||
raw_ip6.c \
|
||||
route6.c \
|
||||
scope6.c \
|
||||
send.c \
|
||||
udp6_usrreq.c \
|
||||
in6_cksum.c \
|
||||
in6_fib.c \
|
||||
in6_gif.c
|
||||
#ip6_gre.c
|
||||
#ip6_ipsec.c
|
||||
#sctp6_usrreq.c
|
||||
#in6_rss.c
|
||||
endif
|
||||
|
||||
ifdef FF_IPFW
|
||||
NETIPFW_SRCS+= \
|
||||
ip_fw_dynamic.c \
|
||||
|
@ -460,6 +505,10 @@ endif
|
|||
ifdef FF_IPSEC
|
||||
NETINET_SRCS+= \
|
||||
ip_ipsec.c
|
||||
ifdef FF_INET6
|
||||
NETINET6_SRCS+= \
|
||||
ip6_ipsec.c
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
|
@ -480,9 +529,6 @@ endif
|
|||
# only if TCP_SIGNTAURE is defined
|
||||
#xform_tcp.c
|
||||
|
||||
NETINET6_SRCS+=
|
||||
|
||||
|
||||
ifdef FF_IPSEC
|
||||
OPENCRYPTO_SRCS+= \
|
||||
cast.c \
|
||||
|
|
16
lib/ff_api.h
16
lib/ff_api.h
|
@ -41,9 +41,23 @@ extern "C" {
|
|||
|
||||
struct linux_sockaddr {
|
||||
short sa_family;
|
||||
char sa_data[14];
|
||||
char sa_data[126];
|
||||
};
|
||||
|
||||
/* AF_INET6/PF_INET6 is 10 in linux
|
||||
* defined 28 for FreeBSD
|
||||
*/
|
||||
#ifdef AF_INET6
|
||||
#undef AF_INET6
|
||||
#endif
|
||||
#ifdef PF_INET6
|
||||
#undef PF_INET6
|
||||
#endif
|
||||
#define AF_INET6 28
|
||||
#define PF_INET6 AF_INET6
|
||||
#define AF_INET6_LINUX 10
|
||||
#define PF_INET6_LINUX AF_INET6
|
||||
|
||||
typedef int (*loop_func_t)(void *arg);
|
||||
|
||||
int ff_init(int argc, char * const argv[]);
|
||||
|
|
|
@ -845,8 +845,9 @@ protocol_filter(const void *data, uint16_t len)
|
|||
|
||||
const struct ether_hdr *hdr;
|
||||
hdr = (const struct ether_hdr *)data;
|
||||
uint16_t eth_frame_type = rte_be_to_cpu_16(hdr->ether_type);
|
||||
|
||||
if(ntohs(hdr->ether_type) == ETHER_TYPE_ARP)
|
||||
if(eth_frame_type == ETHER_TYPE_ARP)
|
||||
return FILTER_ARP;
|
||||
|
||||
#ifndef FF_KNI
|
||||
|
@ -856,11 +857,15 @@ protocol_filter(const void *data, uint16_t len)
|
|||
return FILTER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(ntohs(hdr->ether_type) != ETHER_TYPE_IPv4)
|
||||
if(eth_frame_type != ETHER_TYPE_IPv4
|
||||
#ifdef INET6
|
||||
&& eth_frame_type != ETHER_TYPE_IPv6
|
||||
#endif
|
||||
)
|
||||
return FILTER_UNKNOWN;
|
||||
|
||||
return ff_kni_proto_filter(data + ETHER_HDR_LEN,
|
||||
len - ETHER_HDR_LEN);
|
||||
len - ETHER_HDR_LEN, eth_frame_type);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1053,7 +1058,13 @@ static inline void
|
|||
handle_ioctl_msg(struct ff_msg *msg)
|
||||
{
|
||||
int fd, ret;
|
||||
fd = ff_socket(AF_INET, SOCK_DGRAM, 0);
|
||||
#ifdef INET6
|
||||
if (msg->msg_type == FF_IOCTL6) {
|
||||
fd = ff_socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
} else
|
||||
#endif
|
||||
fd = ff_socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (fd < 0) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
|
@ -1164,6 +1175,9 @@ handle_msg(struct ff_msg *msg, uint16_t proc_id)
|
|||
handle_sysctl_msg(msg);
|
||||
break;
|
||||
case FF_IOCTL:
|
||||
#ifdef INET6
|
||||
case FF_IOCTL6:
|
||||
#endif
|
||||
handle_ioctl_msg(msg);
|
||||
break;
|
||||
case FF_ROUTE:
|
||||
|
|
|
@ -322,38 +322,111 @@ protocol_filter_udp(const void* data,uint16_t len)
|
|||
return protocol_filter_l4(hdr->dst_port, udp_port_bitmap);
|
||||
}
|
||||
|
||||
static enum FilterReturn
|
||||
protocol_filter_ip(const void *data, uint16_t len)
|
||||
#ifdef INET6
|
||||
/*
|
||||
* https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml
|
||||
*/
|
||||
#ifndef IPPROTO_HIP
|
||||
#define IPPROTO_HIP 139
|
||||
#endif
|
||||
|
||||
#ifndef IPPROTO_SHIM6
|
||||
#define IPPROTO_SHIM6 140
|
||||
#endif
|
||||
static int
|
||||
get_ipv6_hdr_len(uint8_t *proto, void *data, uint16_t len)
|
||||
{
|
||||
if(len < sizeof(struct ipv4_hdr))
|
||||
int ext_hdr_len = 0;
|
||||
|
||||
switch (*proto) {
|
||||
case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_MH: case IPPROTO_HIP: case IPPROTO_SHIM6:
|
||||
ext_hdr_len = *((uint8_t *)data + 1) + 1;
|
||||
break;
|
||||
case IPPROTO_FRAGMENT:
|
||||
ext_hdr_len = 8;
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
ext_hdr_len = (*((uint8_t *)data + 1) + 2) * 4;
|
||||
break;
|
||||
case IPPROTO_NONE:
|
||||
#ifdef FF_IPSEC
|
||||
case IPPROTO_ESP:
|
||||
//proto = *((uint8_t *)data + len - 1 - 4);
|
||||
//ext_hdr_len = len;
|
||||
#endif
|
||||
default:
|
||||
return ext_hdr_len;
|
||||
}
|
||||
|
||||
if (ext_hdr_len >= len) {
|
||||
return len;
|
||||
}
|
||||
|
||||
*proto = *((uint8_t *)data);
|
||||
ext_hdr_len += get_ipv6_hdr_len(proto, data + ext_hdr_len, len - ext_hdr_len);
|
||||
|
||||
return ext_hdr_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum FilterReturn
|
||||
protocol_filter_ip(const void *data, uint16_t len, uint16_t eth_frame_type)
|
||||
{
|
||||
uint8_t proto;
|
||||
int hdr_len;
|
||||
void *next;
|
||||
uint16_t next_len;
|
||||
|
||||
if (eth_frame_type == ETHER_TYPE_IPv4) {
|
||||
if(len < sizeof(struct ipv4_hdr))
|
||||
return FILTER_UNKNOWN;
|
||||
|
||||
const struct ipv4_hdr *hdr = (struct ipv4_hdr *)data;
|
||||
hdr_len = (hdr->version_ihl & 0x0f) << 2;
|
||||
if (len < hdr_len)
|
||||
return FILTER_UNKNOWN;
|
||||
|
||||
proto = hdr->next_proto_id;
|
||||
#ifdef INET6
|
||||
} else if(eth_frame_type == ETHER_TYPE_IPv6) {
|
||||
if(len < sizeof(struct ipv6_hdr))
|
||||
return FILTER_UNKNOWN;
|
||||
|
||||
hdr_len = sizeof(struct ipv6_hdr);
|
||||
proto = ((struct ipv6_hdr *)data)->proto;
|
||||
hdr_len += get_ipv6_hdr_len(&proto, (void *)data + hdr_len, len - hdr_len);
|
||||
|
||||
if (len < hdr_len)
|
||||
return FILTER_UNKNOWN;
|
||||
#endif
|
||||
} else {
|
||||
return FILTER_UNKNOWN;
|
||||
}
|
||||
|
||||
const struct ipv4_hdr *hdr;
|
||||
hdr = (const struct ipv4_hdr *)data;
|
||||
next = (void *)data + hdr_len;
|
||||
next_len = len - hdr_len;
|
||||
|
||||
int hdr_len = (hdr->version_ihl & 0x0f) << 2;
|
||||
if (len < hdr_len)
|
||||
return FILTER_UNKNOWN;
|
||||
|
||||
void *next = (void *)data + hdr_len;
|
||||
uint16_t next_len = len - hdr_len;
|
||||
|
||||
switch (hdr->next_proto_id) {
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
return protocol_filter_tcp(next, next_len);
|
||||
case IPPROTO_UDP:
|
||||
return protocol_filter_udp(next, next_len);
|
||||
case IPPROTO_IPIP:
|
||||
return protocol_filter_ip(next, next_len);
|
||||
return protocol_filter_ip(next, next_len, ETHER_TYPE_IPv4);
|
||||
#ifdef INET6
|
||||
case IPPROTO_IPV6:
|
||||
return protocol_filter_ip(next, next_len, ETHER_TYPE_IPv6);
|
||||
#endif
|
||||
}
|
||||
|
||||
return FILTER_UNKNOWN;
|
||||
}
|
||||
|
||||
enum FilterReturn
|
||||
ff_kni_proto_filter(const void *data, uint16_t len)
|
||||
ff_kni_proto_filter(const void *data, uint16_t len, uint16_t eth_frame_type)
|
||||
{
|
||||
return protocol_filter_ip(data, len);
|
||||
return protocol_filter_ip(data, len, eth_frame_type);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -46,7 +46,7 @@ void ff_kni_alloc(uint16_t port_id, unsigned socket_id,
|
|||
void ff_kni_process(uint16_t port_id, uint16_t queue_id,
|
||||
struct rte_mbuf **pkts_burst, unsigned count);
|
||||
|
||||
enum FilterReturn ff_kni_proto_filter(const void *data, uint16_t len);
|
||||
enum FilterReturn ff_kni_proto_filter(const void *data, uint16_t len, uint16_t eth_frame_type);
|
||||
|
||||
int ff_kni_enqueue(uint16_t port_id, struct rte_mbuf *pkt);
|
||||
|
||||
|
|
|
@ -95,7 +95,6 @@ static MALLOC_DEFINE(M_CRED, "cred", "credentials");
|
|||
static MALLOC_DEFINE(M_PLIMIT, "plimit", "plimit structures");
|
||||
|
||||
MALLOC_DEFINE(M_IP6OPT, "ip6opt", "IPv6 options");
|
||||
MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery");
|
||||
|
||||
static void configure_final(void *dummy);
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ enum FF_MSG_TYPE {
|
|||
FF_UNKNOWN = 0,
|
||||
FF_SYSCTL,
|
||||
FF_IOCTL,
|
||||
#ifdef INET6
|
||||
FF_IOCTL6,
|
||||
#endif
|
||||
FF_ROUTE,
|
||||
FF_TOP,
|
||||
FF_NGCTL,
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
#include <net/route.h>
|
||||
#include <net/route_var.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/scope6_var.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#endif
|
||||
|
||||
#include "ff_api.h"
|
||||
#include "ff_host_interface.h"
|
||||
|
|
|
@ -404,7 +404,8 @@ linux2freebsd_sockaddr(const struct linux_sockaddr *linux,
|
|||
/* #linux and #freebsd may point to the same address */
|
||||
freebsd->sa_family = linux->sa_family;
|
||||
freebsd->sa_len = addrlen;
|
||||
bcopy(linux->sa_data, freebsd->sa_data, sizeof(linux->sa_data));
|
||||
|
||||
bcopy(linux->sa_data, freebsd->sa_data, addrlen - sizeof(linux->sa_family));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -416,7 +417,8 @@ freebsd2linux_sockaddr(struct linux_sockaddr *linux,
|
|||
}
|
||||
|
||||
linux->sa_family = freebsd->sa_family;
|
||||
bcopy(freebsd->sa_data, linux->sa_data, sizeof(freebsd->sa_data));
|
||||
|
||||
bcopy(freebsd->sa_data, linux->sa_data, freebsd->sa_len - sizeof(linux->sa_family));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -700,8 +702,8 @@ ff_sendto(int s, const void *buf, size_t len, int flags,
|
|||
struct iovec aiov;
|
||||
int rc;
|
||||
|
||||
struct sockaddr bsdaddr;
|
||||
struct sockaddr *pf = &bsdaddr;
|
||||
struct sockaddr_storage bsdaddr;
|
||||
struct sockaddr *pf = (struct sockaddr *)&bsdaddr;
|
||||
|
||||
if (to) {
|
||||
linux2freebsd_sockaddr(to, tolen, pf);
|
||||
|
@ -731,12 +733,12 @@ ssize_t
|
|||
ff_sendmsg(int s, const struct msghdr *msg, int flags)
|
||||
{
|
||||
int rc;
|
||||
struct sockaddr freebsd_sa;
|
||||
struct sockaddr_storage freebsd_sa;
|
||||
void *linux_sa = msg->msg_name;
|
||||
|
||||
if (linux_sa != NULL) {
|
||||
linux2freebsd_sockaddr(linux_sa,
|
||||
sizeof(struct linux_sockaddr), &freebsd_sa);
|
||||
sizeof(struct linux_sockaddr), (struct sockaddr *)&freebsd_sa);
|
||||
__DECONST(struct msghdr *, msg)->msg_name = &freebsd_sa;
|
||||
}
|
||||
|
||||
|
@ -769,7 +771,7 @@ ff_recvfrom(int s, void *buf, size_t len, int flags,
|
|||
struct msghdr msg;
|
||||
struct iovec aiov;
|
||||
int rc;
|
||||
struct sockaddr bsdaddr;
|
||||
struct sockaddr_storage bsdaddr;
|
||||
|
||||
if (fromlen != NULL)
|
||||
msg.msg_namelen = *fromlen;
|
||||
|
@ -790,7 +792,7 @@ ff_recvfrom(int s, void *buf, size_t len, int flags,
|
|||
*fromlen = msg.msg_namelen;
|
||||
|
||||
if (from)
|
||||
freebsd2linux_sockaddr(from, &bsdaddr);
|
||||
freebsd2linux_sockaddr(from, (struct sockaddr *)&bsdaddr);
|
||||
|
||||
return (rc);
|
||||
kern_fail:
|
||||
|
@ -848,7 +850,7 @@ ff_accept(int s, struct linux_sockaddr * addr,
|
|||
int rc;
|
||||
struct file *fp;
|
||||
struct sockaddr *pf = NULL;
|
||||
socklen_t socklen = sizeof(struct sockaddr);
|
||||
socklen_t socklen = sizeof(struct sockaddr_storage);
|
||||
|
||||
if ((rc = kern_accept(curthread, s, &pf, &socklen, &fp)))
|
||||
goto kern_fail;
|
||||
|
@ -860,7 +862,7 @@ ff_accept(int s, struct linux_sockaddr * addr,
|
|||
freebsd2linux_sockaddr(addr, pf);
|
||||
|
||||
if (addrlen)
|
||||
*addrlen = socklen;
|
||||
*addrlen = pf->sa_len;
|
||||
|
||||
if(pf != NULL)
|
||||
free(pf, M_SONAME);
|
||||
|
@ -894,10 +896,10 @@ int
|
|||
ff_bind(int s, const struct linux_sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int rc;
|
||||
struct sockaddr bsdaddr;
|
||||
linux2freebsd_sockaddr(addr, addrlen, &bsdaddr);
|
||||
struct sockaddr_storage bsdaddr;
|
||||
linux2freebsd_sockaddr(addr, addrlen, (struct sockaddr *)&bsdaddr);
|
||||
|
||||
if ((rc = kern_bindat(curthread, AT_FDCWD, s, &bsdaddr)))
|
||||
if ((rc = kern_bindat(curthread, AT_FDCWD, s, (struct sockaddr *)&bsdaddr)))
|
||||
goto kern_fail;
|
||||
|
||||
return (rc);
|
||||
|
@ -910,10 +912,10 @@ int
|
|||
ff_connect(int s, const struct linux_sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
int rc;
|
||||
struct sockaddr bsdaddr;
|
||||
linux2freebsd_sockaddr(name, namelen, &bsdaddr);
|
||||
struct sockaddr_storage bsdaddr;
|
||||
linux2freebsd_sockaddr(name, namelen, (struct sockaddr *)&bsdaddr);
|
||||
|
||||
if ((rc = kern_connectat(curthread, AT_FDCWD, s, &bsdaddr)))
|
||||
if ((rc = kern_connectat(curthread, AT_FDCWD, s, (struct sockaddr *)&bsdaddr)))
|
||||
goto kern_fail;
|
||||
|
||||
return (rc);
|
||||
|
@ -1202,7 +1204,7 @@ ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag,
|
|||
struct linux_sockaddr *netmask)
|
||||
|
||||
{
|
||||
struct sockaddr sa_gw, sa_dst, sa_nm;
|
||||
struct sockaddr_storage sa_gw, sa_dst, sa_nm;
|
||||
struct sockaddr *psa_gw, *psa_dst, *psa_nm;
|
||||
int rtreq, rtflag;
|
||||
int rc;
|
||||
|
@ -1235,21 +1237,21 @@ ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag,
|
|||
};
|
||||
|
||||
if (gw != NULL) {
|
||||
psa_gw = &sa_gw;
|
||||
psa_gw = (struct sockaddr *)&sa_gw;
|
||||
linux2freebsd_sockaddr(gw, sizeof(*gw), psa_gw);
|
||||
} else {
|
||||
psa_gw = NULL;
|
||||
}
|
||||
|
||||
if (dst != NULL) {
|
||||
psa_dst = &sa_dst;
|
||||
psa_dst = (struct sockaddr *)&sa_dst;
|
||||
linux2freebsd_sockaddr(dst, sizeof(*dst), psa_dst);
|
||||
} else {
|
||||
psa_dst = NULL;
|
||||
}
|
||||
|
||||
if (netmask != NULL) {
|
||||
psa_nm = &sa_nm;
|
||||
psa_nm = (struct sockaddr *)&sa_nm;
|
||||
linux2freebsd_sockaddr(netmask, sizeof(*netmask), psa_nm);
|
||||
} else {
|
||||
psa_nm = NULL;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#define INET6 1
|
Loading…
Reference in New Issue