Subject: Merging port numbers.
To: None <tech-net@netbsd.org>
From: Darren Reed <darrenr@reed.wattle.id.au>
List: tech-net
Date: 07/22/2000 21:29:51
Amongst the idle chatter on icb, there was a bit of talk about how bad
dealing with 16bit things is. One of the more obvious uses of 16bit
things in the kernel is TCP/UDP (for port numbers). The patches below
introduce some more evilness (in the guise of unions) within the TCP
and UDP headers to present the port numbers as a combined 32bit entity.
I've not tested this at all as I'm just curious to get a feeling for
this. In a number of places it allows a reduction in the number of
parameters passed to lookup functions as well as reducing the code
path length for comparisons. IPv6 & IPv4 patches included.
Comments ? Is this sort of evilness welcome within NetBSD for whatever
minimal performance gain it might provide ?
Darren
Index: in6_pcb.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/in6_pcb.c,v
retrieving revision 1.29
diff -c -r1.29 in6_pcb.c
*** in6_pcb.c 2000/07/07 15:54:18 1.29
--- in6_pcb.c 2000/07/23 04:22:32
***************
*** 731,750 ****
}
struct in6pcb *
! in6_pcblookup_connect(head, faddr6, fport_arg, laddr6, lport_arg, faith)
struct in6pcb *head;
struct in6_addr *faddr6, *laddr6;
! u_int fport_arg, lport_arg;
int faith;
{
struct in6pcb *in6p;
- u_int16_t fport = fport_arg, lport = lport_arg;
for (in6p = head->in6p_next; in6p != head; in6p = in6p->in6p_next) {
/* find exact match on both source and dest */
! if (in6p->in6p_fport != fport)
! continue;
! if (in6p->in6p_lport != lport)
continue;
if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr))
continue;
--- 731,747 ----
}
struct in6pcb *
! in6_pcblookup_connect(head, faddr6, laddr6, ports, faith)
struct in6pcb *head;
struct in6_addr *faddr6, *laddr6;
! u_int32_t ports;
int faith;
{
struct in6pcb *in6p;
for (in6p = head->in6p_next; in6p != head; in6p = in6p->in6p_next) {
/* find exact match on both source and dest */
! if (in6p->in6p_ports != ports)
continue;
if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr))
continue;
Index: in6_pcb.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/in6_pcb.h,v
retrieving revision 1.12
diff -c -r1.12 in6_pcb.h
*** in6_pcb.h 2000/07/07 15:54:18 1.12
--- in6_pcb.h 2000/07/23 04:22:36
***************
*** 86,94 ****
struct in6pcb *in6p_head; /* pointer back to chain of
in6pcb's for this protocol */
struct in6_addr in6p_faddr; /* foreign host table entry */
- u_int16_t in6p_fport; /* foreign port */
struct in6_addr in6p_laddr; /* local host table entry */
! u_int16_t in6p_lport; /* local port */
u_int32_t in6p_flowinfo; /* priority and flowlabel */
struct socket *in6p_socket; /* back pointer to socket */
caddr_t in6p_ppcb; /* pointer to per-protocol pcb */
--- 86,99 ----
struct in6pcb *in6p_head; /* pointer back to chain of
in6pcb's for this protocol */
struct in6_addr in6p_faddr; /* foreign host table entry */
struct in6_addr in6p_laddr; /* local host table entry */
! union {
! u_int16_t in6pu_port[2];
! u_int16_t in6pu_ports;
! } in6p_un;
! #define in6p_fport in6p_un.in6pu_port[0] /* foreign port */
! #define in6p_lport in6p_un.in6pu_port[1] /* local port */
! #define in6p_ports in6p_un.in6pu_ports
u_int32_t in6p_flowinfo; /* priority and flowlabel */
struct socket *in6p_socket; /* back pointer to socket */
caddr_t in6p_ppcb; /* pointer to per-protocol pcb */
***************
*** 186,192 ****
extern struct rtentry *
in6_pcbrtentry __P((struct in6pcb *));
extern struct in6pcb *in6_pcblookup_connect __P((struct in6pcb *,
! struct in6_addr *, u_int, struct in6_addr *, u_int, int));
extern struct in6pcb *in6_pcblookup_bind __P((struct in6pcb *,
struct in6_addr *, u_int, int));
#endif
--- 191,197 ----
extern struct rtentry *
in6_pcbrtentry __P((struct in6pcb *));
extern struct in6pcb *in6_pcblookup_connect __P((struct in6pcb *,
! struct in6_addr *, struct in6_addr *, u_int32_t, int));
extern struct in6pcb *in6_pcblookup_bind __P((struct in6pcb *,
struct in6_addr *, u_int, int));
#endif
Index: tcp.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/tcp.h,v
retrieving revision 1.12
diff -c -r1.12 tcp.h
*** tcp.h 2000/07/05 02:45:03 1.12
--- tcp.h 2000/07/23 04:23:49
***************
*** 44,51 ****
* Per RFC 793, September, 1981.
*/
struct tcphdr {
! u_int16_t th_sport; /* source port */
! u_int16_t th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
--- 44,56 ----
* Per RFC 793, September, 1981.
*/
struct tcphdr {
! union {
! u_int16_t thu_port[2];
! u_int32_t thu_ports;
! } th_un;
! #define th_sport th_un.thu_port[2] /* source port */
! #define th_dport th_un.thu_port[1] /* destination port */
! #define th_ports th_un.thu_ports /* combined ports */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
Index: in_pcb.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/in_pcb.c,v
retrieving revision 1.66
diff -c -r1.66 in_pcb.c
*** in_pcb.c 2000/07/06 12:51:39 1.66
--- in_pcb.c 2000/07/23 04:24:00
***************
*** 339,344 ****
--- 339,345 ----
struct in_ifaddr *ia;
struct sockaddr_in *ifaddr = NULL;
struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
+ u_int32_t ports;
int error;
if (nam->m_len != sizeof (*sin))
***************
*** 462,470 ****
}
#endif
}
! if (in_pcblookup_connect(inp->inp_table, sin->sin_addr, sin->sin_port,
!in_nullhost(inp->inp_laddr) ? inp->inp_laddr : ifaddr->sin_addr,
! inp->inp_lport) != 0)
return (EADDRINUSE);
if (in_nullhost(inp->inp_laddr)) {
if (inp->inp_lport == 0) {
--- 463,472 ----
}
#endif
}
! ports = (sin->sin_port << 16) | inp->inp_lport;
! if (in_pcblookup_connect(inp->inp_table, sin->sin_addr,
!in_nullhost(inp->inp_laddr) ? inp->inp_laddr : ifaddr->sin_addr,
! ports) != 0)
return (EADDRINUSE);
if (in_nullhost(inp->inp_laddr)) {
if (inp->inp_lport == 0) {
***************
*** 764,783 ****
#endif
struct inpcb *
! in_pcblookup_connect(table, faddr, fport_arg, laddr, lport_arg)
struct inpcbtable *table;
struct in_addr faddr, laddr;
! u_int fport_arg, lport_arg;
{
struct inpcbhead *head;
struct inpcb *inp;
- u_int16_t fport = fport_arg, lport = lport_arg;
head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport);
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
if (in_hosteq(inp->inp_faddr, faddr) &&
! inp->inp_fport == fport &&
! inp->inp_lport == lport &&
in_hosteq(inp->inp_laddr, laddr))
goto out;
}
--- 766,783 ----
#endif
struct inpcb *
! in_pcblookup_connect(table, faddr, laddr, ports)
struct inpcbtable *table;
struct in_addr faddr, laddr;
! u_in32_t ports;
{
struct inpcbhead *head;
struct inpcb *inp;
head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport);
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
if (in_hosteq(inp->inp_faddr, faddr) &&
! inp->inp_ports == ports &&
in_hosteq(inp->inp_laddr, laddr))
goto out;
}
Index: in_pcb.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/in_pcb.h,v
retrieving revision 1.29
diff -c -r1.29 in_pcb.h
*** in_pcb.h 2000/02/02 23:28:09 1.29
--- in_pcb.h 2000/07/23 04:24:04
***************
*** 84,91 ****
CIRCLEQ_ENTRY(inpcb) inp_queue;
caddr_t inp_ppcb; /* pointer to per-protocol pcb */
int inp_state; /* bind/connect state */
! u_int16_t inp_fport; /* foreign port */
! u_int16_t inp_lport; /* local port */
struct socket *inp_socket; /* back pointer to socket */
struct route inp_route; /* placeholder for routing entry */
int inp_flags; /* generic IP/datagram flags */
--- 84,96 ----
CIRCLEQ_ENTRY(inpcb) inp_queue;
caddr_t inp_ppcb; /* pointer to per-protocol pcb */
int inp_state; /* bind/connect state */
! union {
! u_int16_t inpu_port[2];
! u_int32_t inpu_ports;
! } inp_un;
! #define inp_fport inp_un.inpu_port[0] /* foreign port */
! #define inp_lport inp_un.inpu_port[1] /* local port */
! #define inp_ports inp_un.inpu_ports
struct socket *inp_socket; /* back pointer to socket */
struct route inp_route; /* placeholder for routing entry */
int inp_flags; /* generic IP/datagram flags */
***************
*** 146,152 ****
struct in_addr, u_int));
struct inpcb *
in_pcblookup_connect __P((struct inpcbtable *,
! struct in_addr, u_int, struct in_addr, u_int));
int in_pcbnotify __P((struct inpcbtable *, struct in_addr, u_int,
struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
void in_pcbnotifyall __P((struct inpcbtable *, struct in_addr, int,
--- 151,157 ----
struct in_addr, u_int));
struct inpcb *
in_pcblookup_connect __P((struct inpcbtable *,
! struct in_addr, struct in_addr, u_int32_t));
int in_pcbnotify __P((struct inpcbtable *, struct in_addr, u_int,
struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
void in_pcbnotifyall __P((struct inpcbtable *, struct in_addr, int,
Index: udp.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/udp.h,v
retrieving revision 1.9
diff -c -r1.9 udp.h
*** udp.h 1999/11/20 00:38:00 1.9
--- udp.h 2000/07/23 04:24:06
***************
*** 43,50 ****
* Per RFC 768, September, 1981.
*/
struct udphdr {
! u_int16_t uh_sport; /* source port */
! u_int16_t uh_dport; /* destination port */
u_int16_t uh_ulen; /* udp length */
u_int16_t uh_sum; /* udp checksum */
} __attribute__((__packed__));
--- 43,55 ----
* Per RFC 768, September, 1981.
*/
struct udphdr {
! union {
! u_int16_t uhu_port[2];
! u_int32_t uhu_ports;
! } uh_un;
! #define uh_sport uh_un.uhu_port[0] /* source port */
! #define uh_dport uh_un.uhu_port[1] /* destination port */
! #define uh_ports uh_un.uhu_ports
u_int16_t uh_ulen; /* udp length */
u_int16_t uh_sum; /* udp checksum */
} __attribute__((__packed__));
Index: tcp_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/tcp_input.c,v
retrieving revision 1.113
diff -c -r1.113 tcp_input.c
*** tcp_input.c 2000/07/09 12:49:08 1.113
--- tcp_input.c 2000/07/23 04:24:44
***************
*** 787,794 ****
#endif
switch (af) {
case AF_INET:
! inp = in_pcblookup_connect(&tcbtable, ip->ip_src, th->th_sport,
! ip->ip_dst, th->th_dport);
if (inp == 0) {
++tcpstat.tcps_pcbhashmiss;
inp = in_pcblookup_bind(&tcbtable, ip->ip_dst, th->th_dport);
--- 787,794 ----
#endif
switch (af) {
case AF_INET:
! inp = in_pcblookup_connect(&tcbtable, ip->ip_src, ip->ip_dst,
! th->th_ports);
if (inp == 0) {
++tcpstat.tcps_pcbhashmiss;
inp = in_pcblookup_bind(&tcbtable, ip->ip_dst, th->th_dport);
***************
*** 804,811 ****
bzero(&d, sizeof(d));
d.s6_addr16[5] = htons(0xffff);
bcopy(&ip->ip_dst, &d.s6_addr32[3], sizeof(ip->ip_dst));
! in6p = in6_pcblookup_connect(&tcb6, &s, th->th_sport,
! &d, th->th_dport, 0);
if (in6p == 0) {
++tcpstat.tcps_pcbhashmiss;
in6p = in6_pcblookup_bind(&tcb6, &d,
--- 804,811 ----
bzero(&d, sizeof(d));
d.s6_addr16[5] = htons(0xffff);
bcopy(&ip->ip_dst, &d.s6_addr32[3], sizeof(ip->ip_dst));
! in6p = in6_pcblookup_connect(&tcb6, &s, &d,
! th->th_ports, 0);
if (in6p == 0) {
++tcpstat.tcps_pcbhashmiss;
in6p = in6_pcblookup_bind(&tcb6, &d,
***************
*** 877,884 ****
#else
faith = 0;
#endif
! in6p = in6_pcblookup_connect(&tcb6, &ip6->ip6_src, th->th_sport,
! &ip6->ip6_dst, th->th_dport, faith);
if (in6p == NULL) {
++tcpstat.tcps_pcbhashmiss;
in6p = in6_pcblookup_bind(&tcb6, &ip6->ip6_dst,
--- 877,884 ----
#else
faith = 0;
#endif
! in6p = in6_pcblookup_connect(&tcb6, &ip6->ip6_src,
! &ip6->ip6_dst, th->th_ports, faith);
if (in6p == NULL) {
++tcpstat.tcps_pcbhashmiss;
in6p = in6_pcblookup_bind(&tcb6, &ip6->ip6_dst,
Index: udp_usrreq.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/udp_usrreq.c,v
retrieving revision 1.69
diff -c -r1.69 udp_usrreq.c
*** udp_usrreq.c 2000/07/07 15:54:16 1.69
--- udp_usrreq.c 2000/07/23 04:24:59
***************
*** 528,536 ****
int off; /* offset of udphdr */
{
u_int16_t *sport, *dport;
- int rcvcnt;
struct in_addr *src4, *dst4;
struct inpcb *inp;
rcvcnt = 0;
off += sizeof(struct udphdr); /* now, offset of payload */
--- 528,537 ----
int off; /* offset of udphdr */
{
u_int16_t *sport, *dport;
struct in_addr *src4, *dst4;
struct inpcb *inp;
+ u_int32_t ports;
+ int rcvcnt;
rcvcnt = 0;
off += sizeof(struct udphdr); /* now, offset of payload */
***************
*** 542,547 ****
--- 543,549 ----
sport = &src->sin_port;
dst4 = &dst->sin_addr;
dport = &dst->sin_port;
+ ports = (sport << 16) | dport;
if (IN_MULTICAST(src4->s_addr) ||
in_broadcast(*dst4, m->m_pkthdr.rcvif)) {
***************
*** 617,623 ****
/*
* Locate pcb for datagram.
*/
! inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport);
if (inp == 0) {
++udpstat.udps_pcbhashmiss;
inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
--- 619,625 ----
/*
* Locate pcb for datagram.
*/
! inp = in_pcblookup_connect(&udbtable, *src4, *dst4, ports);
if (inp == 0) {
++udpstat.udps_pcbhashmiss;
inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
***************
*** 690,699 ****
int off; /* offset of udphdr */
{
u_int16_t *sport, *dport;
- int rcvcnt;
struct in6_addr *src6, *dst6;
struct in_addr *src4;
struct in6pcb *in6p;
rcvcnt = 0;
off += sizeof(struct udphdr); /* now, offset of payload */
--- 692,702 ----
int off; /* offset of udphdr */
{
u_int16_t *sport, *dport;
struct in6_addr *src6, *dst6;
struct in_addr *src4;
struct in6pcb *in6p;
+ u_int32_t ports;
+ int rcvcnt;
rcvcnt = 0;
off += sizeof(struct udphdr); /* now, offset of payload */
***************
*** 707,712 ****
--- 710,716 ----
sport = &src->sin6_port;
dst6 = &dst->sin6_addr;
dport = &dst->sin6_port;
+ ports = (sport << 16) | dport;
src4 = (struct in_addr *)&src->sin6_addr.s6_addr32[12];
if (IN6_IS_ADDR_MULTICAST(dst6)
***************
*** 804,811 ****
/*
* Locate pcb for datagram.
*/
! in6p = in6_pcblookup_connect(&udb6, src6, *sport,
! dst6, *dport, 0);
if (in6p == 0) {
++udpstat.udps_pcbhashmiss;
in6p = in6_pcblookup_bind(&udb6, dst6, *dport, 0);
--- 808,814 ----
/*
* Locate pcb for datagram.
*/
! in6p = in6_pcblookup_connect(&udb6, src6, dst6, ports, 0);
if (in6p == 0) {
++udpstat.udps_pcbhashmiss;
in6p = in6_pcblookup_bind(&udb6, dst6, *dport, 0);
***************
*** 1070,1077 ****
/*
* Locate pcb for datagram.
*/
! inp = in_pcblookup_connect(&udbtable, ip->ip_src, uh->uh_sport,
! ip->ip_dst, uh->uh_dport);
if (inp == 0) {
++udpstat.udps_pcbhashmiss;
inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport);
--- 1073,1080 ----
/*
* Locate pcb for datagram.
*/
! inp = in_pcblookup_connect(&udbtable, ip->ip_src, ip->ip_dst,
! uh->uh_ports);
if (inp == 0) {
++udpstat.udps_pcbhashmiss;
inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport);