aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2007-12-30 22:08:12 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-02-01 16:42:12 -0500
commit9dbc240f199c16c3c0859c255ad52a663d8ee51d (patch)
tree0e81dd425c36590e65accfe9654d905632783c7f /net
parent8c7b0172a1db8120d25ecb4eff69664c52ee7639 (diff)
svc: Move the sockaddr information to svc_xprt
This patch moves the transport sockaddr to the svc_xprt structure. Convenience functions are added to set and get the local and remote addresses of a transport from the transport provider as well as determine the length of a sockaddr. A transport is responsible for setting the xpt_local and xpt_remote addresses in the svc_xprt structure as part of transport creation and xpo_accept processing. This cannot be done in a generic way and in fact varies between TCP, UDP and RDMA. A set of xpo_ functions (e.g. getlocalname, getremotename) could have been added but this would have resulted in additional caching and copying of the addresses around. Note that the xpt_local address should also be set on listening endpoints; for TCP/RDMA this is done as part of endpoint creation. For connected transports like TCP and RDMA, the addresses never change and can be set once and copied into the rqstp structure for each request. For UDP, however, the local and remote addresses may change for each request. In this case, the address information is obtained from the UDP recvmsg info and copied into the rqstp structure from there. A svc_xprt_local_port function was also added that returns the local port given a transport. This is used by svc_create_xprt when returning the port associated with a newly created transport, and later when creating a generic find transport service to check if a service is already listening on a given port. Signed-off-by: Tom Tucker <tom@opengridcomputing.com> Acked-by: Neil Brown <neilb@suse.de> Reviewed-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Greg Banks <gnb@sgi.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/svc_xprt.c31
-rw-r--r--net/sunrpc/svcsock.c56
2 files changed, 59 insertions, 28 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 023aeb0ecfa9..eb650af50c49 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -125,7 +125,6 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
125 spin_unlock(&svc_xprt_class_lock); 125 spin_unlock(&svc_xprt_class_lock);
126 if (try_module_get(xcl->xcl_owner)) { 126 if (try_module_get(xcl->xcl_owner)) {
127 struct svc_xprt *newxprt; 127 struct svc_xprt *newxprt;
128 ret = 0;
129 newxprt = xcl->xcl_ops->xpo_create 128 newxprt = xcl->xcl_ops->xpo_create
130 (serv, 129 (serv,
131 (struct sockaddr *)&sin, sizeof(sin), 130 (struct sockaddr *)&sin, sizeof(sin),
@@ -133,7 +132,8 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
133 if (IS_ERR(newxprt)) { 132 if (IS_ERR(newxprt)) {
134 module_put(xcl->xcl_owner); 133 module_put(xcl->xcl_owner);
135 ret = PTR_ERR(newxprt); 134 ret = PTR_ERR(newxprt);
136 } 135 } else
136 ret = svc_xprt_local_port(newxprt);
137 } 137 }
138 goto out; 138 goto out;
139 } 139 }
@@ -144,3 +144,30 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
144 return ret; 144 return ret;
145} 145}
146EXPORT_SYMBOL_GPL(svc_create_xprt); 146EXPORT_SYMBOL_GPL(svc_create_xprt);
147
148/*
149 * Copy the local and remote xprt addresses to the rqstp structure
150 */
151void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt)
152{
153 struct sockaddr *sin;
154
155 memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen);
156 rqstp->rq_addrlen = xprt->xpt_remotelen;
157
158 /*
159 * Destination address in request is needed for binding the
160 * source address in RPC replies/callbacks later.
161 */
162 sin = (struct sockaddr *)&xprt->xpt_local;
163 switch (sin->sa_family) {
164 case AF_INET:
165 rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
166 break;
167 case AF_INET6:
168 rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
169 break;
170 }
171}
172EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs);
173
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 9d0a9e6c0e10..9564d2e9520e 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -623,33 +623,13 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
623 struct msghdr msg = { 623 struct msghdr msg = {
624 .msg_flags = MSG_DONTWAIT, 624 .msg_flags = MSG_DONTWAIT,
625 }; 625 };
626 struct sockaddr *sin;
627 int len; 626 int len;
628 627
629 len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, 628 len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
630 msg.msg_flags); 629 msg.msg_flags);
631 630
632 /* sock_recvmsg doesn't fill in the name/namelen, so we must..
633 */
634 memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
635 rqstp->rq_addrlen = svsk->sk_remotelen;
636
637 /* Destination address in request is needed for binding the
638 * source address in RPC callbacks later.
639 */
640 sin = (struct sockaddr *)&svsk->sk_local;
641 switch (sin->sa_family) {
642 case AF_INET:
643 rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
644 break;
645 case AF_INET6:
646 rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
647 break;
648 }
649
650 dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", 631 dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
651 svsk, iov[0].iov_base, iov[0].iov_len, len); 632 svsk, iov[0].iov_base, iov[0].iov_len, len);
652
653 return len; 633 return len;
654} 634}
655 635
@@ -719,8 +699,15 @@ svc_write_space(struct sock *sk)
719 } 699 }
720} 700}
721 701
722static inline void svc_udp_get_dest_address(struct svc_rqst *rqstp, 702/*
723 struct cmsghdr *cmh) 703 * Copy the UDP datagram's destination address to the rqstp structure.
704 * The 'destination' address in this case is the address to which the
705 * peer sent the datagram, i.e. our local address. For multihomed
706 * hosts, this can change from msg to msg. Note that only the IP
707 * address changes, the port number should remain the same.
708 */
709static void svc_udp_get_dest_address(struct svc_rqst *rqstp,
710 struct cmsghdr *cmh)
724{ 711{
725 switch (rqstp->rq_sock->sk_sk->sk_family) { 712 switch (rqstp->rq_sock->sk_sk->sk_family) {
726 case AF_INET: { 713 case AF_INET: {
@@ -787,7 +774,10 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
787 svc_xprt_received(&svsk->sk_xprt); 774 svc_xprt_received(&svsk->sk_xprt);
788 return -EAGAIN; 775 return -EAGAIN;
789 } 776 }
790 rqstp->rq_addrlen = sizeof(rqstp->rq_addr); 777 len = svc_addr_len(svc_addr(rqstp));
778 if (len < 0)
779 return len;
780 rqstp->rq_addrlen = len;
791 if (skb->tstamp.tv64 == 0) { 781 if (skb->tstamp.tv64 == 0) {
792 skb->tstamp = ktime_get_real(); 782 skb->tstamp = ktime_get_real();
793 /* Don't enable netstamp, sunrpc doesn't 783 /* Don't enable netstamp, sunrpc doesn't
@@ -1097,14 +1087,13 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
1097 if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 1087 if (!(newsvsk = svc_setup_socket(serv, newsock, &err,
1098 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) 1088 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY))))
1099 goto failed; 1089 goto failed;
1100 memcpy(&newsvsk->sk_remote, sin, slen); 1090 svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen);
1101 newsvsk->sk_remotelen = slen;
1102 err = kernel_getsockname(newsock, sin, &slen); 1091 err = kernel_getsockname(newsock, sin, &slen);
1103 if (unlikely(err < 0)) { 1092 if (unlikely(err < 0)) {
1104 dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err); 1093 dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err);
1105 slen = offsetof(struct sockaddr, sa_data); 1094 slen = offsetof(struct sockaddr, sa_data);
1106 } 1095 }
1107 memcpy(&newsvsk->sk_local, sin, slen); 1096 svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen);
1108 1097
1109 if (serv->sv_stats) 1098 if (serv->sv_stats)
1110 serv->sv_stats->nettcpconn++; 1099 serv->sv_stats->nettcpconn++;
@@ -1245,6 +1234,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
1245 svsk->sk_reclen = 0; 1234 svsk->sk_reclen = 0;
1246 svsk->sk_tcplen = 0; 1235 svsk->sk_tcplen = 0;
1247 1236
1237 svc_xprt_copy_addrs(rqstp, &svsk->sk_xprt);
1248 svc_xprt_received(&svsk->sk_xprt); 1238 svc_xprt_received(&svsk->sk_xprt);
1249 if (serv->sv_stats) 1239 if (serv->sv_stats)
1250 serv->sv_stats->nettcpcnt++; 1240 serv->sv_stats->nettcpcnt++;
@@ -1805,6 +1795,11 @@ int svc_addsock(struct svc_serv *serv,
1805 else { 1795 else {
1806 svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS); 1796 svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS);
1807 if (svsk) { 1797 if (svsk) {
1798 struct sockaddr_storage addr;
1799 struct sockaddr *sin = (struct sockaddr *)&addr;
1800 int salen;
1801 if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
1802 svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
1808 svc_xprt_received(&svsk->sk_xprt); 1803 svc_xprt_received(&svsk->sk_xprt);
1809 err = 0; 1804 err = 0;
1810 } 1805 }
@@ -1831,6 +1826,9 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
1831 int error; 1826 int error;
1832 int type; 1827 int type;
1833 char buf[RPC_MAX_ADDRBUFLEN]; 1828 char buf[RPC_MAX_ADDRBUFLEN];
1829 struct sockaddr_storage addr;
1830 struct sockaddr *newsin = (struct sockaddr *)&addr;
1831 int newlen;
1834 1832
1835 dprintk("svc: svc_create_socket(%s, %d, %s)\n", 1833 dprintk("svc: svc_create_socket(%s, %d, %s)\n",
1836 serv->sv_program->pg_name, protocol, 1834 serv->sv_program->pg_name, protocol,
@@ -1855,12 +1853,18 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
1855 if (error < 0) 1853 if (error < 0)
1856 goto bummer; 1854 goto bummer;
1857 1855
1856 newlen = len;
1857 error = kernel_getsockname(sock, newsin, &newlen);
1858 if (error < 0)
1859 goto bummer;
1860
1858 if (protocol == IPPROTO_TCP) { 1861 if (protocol == IPPROTO_TCP) {
1859 if ((error = kernel_listen(sock, 64)) < 0) 1862 if ((error = kernel_listen(sock, 64)) < 0)
1860 goto bummer; 1863 goto bummer;
1861 } 1864 }
1862 1865
1863 if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { 1866 if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
1867 svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
1864 svc_xprt_received(&svsk->sk_xprt); 1868 svc_xprt_received(&svsk->sk_xprt);
1865 return (struct svc_xprt *)svsk; 1869 return (struct svc_xprt *)svsk;
1866 } 1870 }