[netperf-dev] netperf2 commit notice r226 - trunk/src

raj at netperf.org raj at netperf.org
Tue Feb 12 09:36:52 PST 2008


Author: raj
Date: 2008-02-12 09:36:51 -0800 (Tue, 12 Feb 2008)
New Revision: 226

Added:
   trunk/src/netrt_rtnetlink.c
Log:
do not forget netrt_rtnetlink.c

Added: trunk/src/netrt_rtnetlink.c
===================================================================
--- trunk/src/netrt_rtnetlink.c	                        (rev 0)
+++ trunk/src/netrt_rtnetlink.c	2008-02-12 17:36:51 UTC (rev 226)
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bits/sockaddr.h>
+#include <asm/types.h>
+#include <linux/rtnetlink.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netdb.h>
+
+char *
+find_egress_interface(struct sockaddr *source, struct sockaddr *dest) {
+
+  struct sockaddr_nl me,them;
+  struct sockaddr_in  *in4;
+  struct sockaddr_in6 *in6;
+
+  int interface_index = -1;
+  char interface_name[IF_NAMESIZE];
+
+  int s;
+
+  /* so, in our msghdr we will put the address and an iovec pointing
+     to our request.  that request will consist of a netlink message
+     header, a routing message header and some routing attributes.
+     the chalice with the palace holds the pellet with the poison, the
+     vessel with the pestle holds the brew which is true.  i guess it
+     would have been "too easy" to just have a plain old ioctl that
+     one calls to get the route for a given destination and
+     source... raj 2008-02-11 */
+
+  struct msghdr msg;
+ 
+  struct iovec iov;
+ 
+  struct {
+    struct nlmsghdr nl;
+    struct rtmsg    rt;
+    char   buf[1024];
+  } request;
+
+  char reply[1024];
+
+  struct nlmsghdr *nlp;
+  struct rtmsg *rtp;
+  struct rtattr *rtap;
+  int nll,rtl;
+
+  int ret;
+
+  /* create and bind the netlink socket */
+  s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+
+  memset(&me, 0, sizeof(me));
+  me.nl_family = AF_NETLINK;
+  me.nl_pid = getpid();
+
+  /* probably should be checking a return value... */
+  bind(s, (struct sockaddr *)&me, sizeof(me));
+
+  /* create the message we are going to send */
+
+  memset(&request, 0, sizeof(request));
+  request.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+  request.nl.nlmsg_flags = NLM_F_REQUEST;
+  request.nl.nlmsg_type = RTM_GETROUTE;
+
+  /* time to add the destination attribute to the request */
+  if (dest) {
+    in4 = (struct sockaddr_in *)dest;
+    in6 = (struct sockaddr_in6 *)dest;
+    request.rt.rtm_family = in4->sin_family;
+    rtap = (struct rtattr *)request.buf;
+    rtap->rta_type = RTA_DST;
+    if (AF_INET == in4->sin_family) {
+      rtap->rta_len = RTA_LENGTH(sizeof(in4->sin_addr));
+      memcpy(RTA_DATA(rtap), &(in4->sin_addr), sizeof(in4->sin_addr));
+    }
+    else if (AF_INET6 == in6->sin6_family) {
+      rtap->rta_len = RTA_LENGTH(sizeof(in6->sin6_addr));
+      memcpy(RTA_DATA(rtap), &(in6->sin6_addr), sizeof(in6->sin6_addr));
+    }
+    else {
+      return strdup("UnknownAddressFamily");
+    }
+  }
+  else {
+    /* there must always be a destination */
+    printf("No destination specified.\n");
+    return strdup("NoDestination");
+  }
+
+  /* add the length of our request to our overall message length. it
+     should already be suitably padded by the previous RTA_LENGTH */
+  request.nl.nlmsg_len += rtap->rta_len;
+
+  /* now the src */
+  if (source) {
+    /* the source goes after the dest, so we can just increment by the
+       current value of rta_len */
+    in4 = (struct sockaddr_in *)source;
+    in6 = (struct sockaddr_in6 *)source;
+    rtap +=  rtap->rta_len;
+    rtap->rta_type = RTA_SRC;
+    if (AF_INET == in4->sin_family) {
+      rtap->rta_len = RTA_LENGTH(sizeof(in4->sin_addr));
+      memcpy(RTA_DATA(rtap), &(in4->sin_addr), sizeof(in4->sin_addr));
+    }
+    else if (AF_INET6 == in6->sin6_family) {
+      rtap->rta_len = RTA_LENGTH(sizeof(in6->sin6_addr));
+      memcpy(RTA_DATA(rtap), &(in6->sin6_addr), sizeof(in6->sin6_addr));
+    }
+    else {
+      return strdup("UnknownAddressFamily");
+    }
+     
+
+    /* add the length of the just added attribute to the overall
+     message length. it should already be suitably padded by the
+     previous RTA_LENGTH */
+    request.nl.nlmsg_len += rtap->rta_len;
+  }
+  
+  /* address it */
+  memset(&them, 0, sizeof(them));
+  them.nl_family = AF_NETLINK;
+
+  memset(&msg, 0, sizeof(msg));
+  msg.msg_name = (void *)&them;
+  msg.msg_namelen = sizeof(them);
+
+  iov.iov_base = (void *) &request.nl;
+  iov.iov_len  = request.nl.nlmsg_len;
+
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+
+  /* send it */
+  ret = sendmsg(s, &msg, 0);
+
+  if (ret < 0) {
+    return strdup("SendmsgFailure");
+  }
+
+  memset(reply,0,sizeof(reply));
+  ret = recv(s, reply, sizeof(reply), 0);
+  
+  if (ret < 0) {
+    return strdup("RecvmsgFailure");
+  }
+
+  nll = ret;
+
+  /* Since we are looking for a single route, one has to wonder if
+     this is really necessary, but since all the examples I could find
+     seemed to be doing it, I'll simply follow along. raj
+     2008-02-11 */
+
+  for (nlp = (struct nlmsghdr *)reply;
+       NLMSG_OK(nlp,nll);
+       nlp = NLMSG_NEXT(nlp, nll)) {
+    /* where oh where might the route header be? */
+    rtp = (struct rtmsg *) NLMSG_DATA(nlp);
+
+#if 0
+    /* we will ass-u-me we are only interested in results for the main
+       routing table */
+    if (RT_TABLE_MAIN != rtp->rtm_table) {
+      printf("skipping table %d\n",rtp->rtm_table);
+      continue;
+    }
+#endif 
+
+    for (rtap = (struct rtattr *) RTM_RTA(rtp), rtl = RTM_PAYLOAD(nlp);
+	 RTA_OK(rtap, rtl);
+	 rtap = RTA_NEXT(rtap,rtl)) {
+      if (RTA_OIF == rtap->rta_type) {
+	if (-1 == interface_index){
+	  interface_index = *((int *) RTA_DATA(rtap));
+	}
+	else {
+	  printf("Found a second interface index, which was not expected!\n");
+	  return strdup("MultipleInterfacesFound");
+	}
+      }
+    }
+  }
+
+  if (interface_index == -1) {
+    /* we didn't find it */
+    return strdup("InterfaceNotFound");
+  }
+  else {
+    if (NULL == if_indextoname(interface_index,interface_name)) {
+      return strdup("IfIndexToNameFailure");
+    }
+    else {
+      return strdup(interface_name);
+    }
+  }
+}



More information about the netperf-dev mailing list