IPv6: FreeBSD stack and f-stack support ipv6.

dev
fengbojiang(姜凤波) 2019-07-12 20:56:01 +08:00
parent 171a039c22
commit d7140ab746
13 changed files with 214 additions and 47 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 \

View File

@ -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[]);

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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"

View File

@ -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;

View File

@ -0,0 +1 @@
#define INET6 1