netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Ahern <dsa@cumulusnetworks.com>
To: netdev@vger.kernel.org
Cc: shm@cumulusnetworks.com, roopa@cumulusnetworks.com,
	gospo@cumulusnetworks.com, jtoppins@cumulusnetworks.com,
	nikolay@cumulusnetworks.com, ddutt@cumulusnetworks.com,
	hannes@stressinduktion.org, nicolas.dichtel@6wind.com,
	stephen@networkplumber.org, hadi@mojatatu.com,
	ebiederm@xmission.com, davem@davemloft.net, svaidya@brocade.com,
	mingo@kernel.org, luto@amacapital.net,
	David Ahern <dsa@cumulusnetworks.com>
Subject: [PATCH net-next 15/16] net: Add chvrf command
Date: Mon, 27 Jul 2015 12:31:08 -0600	[thread overview]
Message-ID: <1438021869-49186-16-git-send-email-dsa@cumulusnetworks.com> (raw)
In-Reply-To: <1438021869-49186-1-git-send-email-dsa@cumulusnetworks.com>

Example of how to use the default bind to interface option for tasks and
correlate with VRF devices.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 tools/net/Makefile |   6 +-
 tools/net/chvrf.c  | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 229 insertions(+), 2 deletions(-)
 create mode 100644 tools/net/chvrf.c

diff --git a/tools/net/Makefile b/tools/net/Makefile
index ee577ea03ba5..c13f11f5637a 100644
--- a/tools/net/Makefile
+++ b/tools/net/Makefile
@@ -10,7 +10,7 @@ YACC = bison
 %.lex.c: %.l
 	$(LEX) -o $@ $<
 
-all : bpf_jit_disasm bpf_dbg bpf_asm
+all : bpf_jit_disasm bpf_dbg bpf_asm chvrf
 
 bpf_jit_disasm : CFLAGS = -Wall -O2 -DPACKAGE='bpf_jit_disasm'
 bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
@@ -25,8 +25,10 @@ bpf_asm : LDLIBS =
 bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o
 bpf_exp.lex.o : bpf_exp.yacc.c
 
+chvrf : CFLAGS = -Wall -O2
+
 clean :
-	rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.*
+	rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.* chvrf
 
 install :
 	install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
diff --git a/tools/net/chvrf.c b/tools/net/chvrf.c
new file mode 100644
index 000000000000..71cc925fd101
--- /dev/null
+++ b/tools/net/chvrf.c
@@ -0,0 +1,225 @@
+/*
+ * chvrf.c - Example of how to use the default bind-to-device option for
+ *           tasks and correlate to VRFs via the VRF device.
+ *
+ * Copyright (c) 2015 Cumulus Networks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <sys/ioctl.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <net/if.h> /* for struct ifreq  */
+#include <libgen.h>
+#include <errno.h>
+
+#ifndef PR_SET_SK_BIND_DEV_IF
+#define PR_SET_SK_BIND_DEV_IF   47
+#endif
+#ifndef PR_GET_SK_BIND_DEV_IF
+#define PR_GET_SK_BIND_DEV_IF   48
+#endif
+
+static int vrf_to_device(int vrf)
+{
+	struct ifreq ifdata;
+	int sd, rc;
+
+	memset(&ifdata, 0, sizeof(ifdata));
+	snprintf(ifdata.ifr_name, sizeof(ifdata.ifr_name) - 1, "vrf%d", vrf);
+
+	sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+	if (sd < 0) {
+		perror("socket failed");
+		return -1;
+	}
+
+	/* Get the index for the specified interface */
+	rc = ioctl(sd, SIOCGIFINDEX, (char *)&ifdata);
+	close(sd);
+	if (rc != 0) {
+		perror("ioctl(SIOCGIFINDEX) failed");
+		return -1;
+	}
+
+	return ifdata.ifr_ifindex;
+}
+
+static int device_to_vrf(int idx)
+{
+	struct ifreq ifdata;
+	int sd, vrf, rc;
+
+	memset(&ifdata, 0, sizeof(ifdata));
+	ifdata.ifr_ifindex = idx;
+
+	sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+	if (sd < 0) {
+		perror("socket failed");
+		return -1;
+	}
+
+	/* Get the index for the specified interface */
+	rc = ioctl(sd, SIOCGIFNAME, (char *)&ifdata);
+	close(sd);
+	if (rc != 0) {
+		perror("ioctl(SIOCGIFNAME) failed");
+		return -1;
+	}
+
+	if (sscanf(ifdata.ifr_name, "vrf%d", &vrf) != 1) {
+		fprintf(stderr, "Unexpected device name (%s)\n", ifdata.ifr_name);
+		vrf = -1;
+	}
+
+	return vrf;
+}
+
+static int set_vrf(int vrf)
+{
+	int idx;
+	long err;
+
+	/* convert vrf to device index */
+	idx = vrf_to_device(vrf);
+	if (idx < 0) {
+		fprintf(stderr, "Failed to get device index for vrf %d\n", vrf);
+		return -1;
+	}
+
+	/* set default device bind */
+	err = prctl(PR_SET_SK_BIND_DEV_IF, idx);
+	if (err < 0) {
+		fprintf(stderr, "prctl failed to device index: %d\n", errno);
+		return -1;
+	}
+
+	return 0;
+}
+
+/* get vrf context for given process id */
+static int get_vrf(pid_t pid)
+{
+	int vrf;
+	long err;
+
+	/* lookup device index pid is tied to */
+	err = prctl(PR_GET_SK_BIND_DEV_IF, pid);
+	if (err < 0) {
+		fprintf(stderr, "prctl failed: %d\n", errno);
+		return -1;
+	}
+
+	if (err == 0)
+		return 0;
+
+	/* convert device index to vrf id */
+	vrf = device_to_vrf((int)err);
+	if (vrf < 0) {
+		fprintf(stderr, "Failed to get device index for vrf %d\n", vrf);
+		return -1;
+	}
+
+	return vrf;
+}
+
+static int run_vrf(char **argv, int vrf)
+{
+	char *cmd;
+
+	if (set_vrf(vrf) != 0) {
+		fprintf(stderr, "Failed to set vrf context\n");
+		return 1;
+	}
+
+	cmd = strdup(argv[0]);
+	if (!cmd) {
+		fprintf(stderr, "Failed to set command\n");
+		return 1;
+	}
+	argv[0] = basename(argv[0]);
+	if (execvp(cmd, argv) < 0)
+		perror("Failed to exec command\n");
+
+	return 1;
+}
+
+static int show_vrf(pid_t pid)
+{
+	int vrf = get_vrf(pid);
+
+	switch (vrf) {
+	case -1:
+		fprintf(stderr, "Failed to get vrf context for pid %d\n", pid);
+		if (kill(pid, 0) < 0) {
+			if (errno == ESRCH)
+				fprintf(stderr, "No process with given pid\n");
+		}
+		break;
+	case 0:
+		printf("Process %d is not running in a VRF context\n", pid);
+		break;
+	default:
+		printf("Process %d is running in VRF %d\n", pid, vrf);
+	}
+	return vrf < 0 ? 1 : 0;
+}
+
+static void usage(char *_prog)
+{
+	const char *prog = basename(_prog);
+
+	fprintf(stderr, "usage:\n");
+	fprintf(stderr, "\nShow VRF context for given pid\n");
+	fprintf(stderr, "\t%s -p pid\n", prog);
+	fprintf(stderr, "\nRun command in given VRF context\n");
+	fprintf(stderr, "\t%s -v vrf <command>\n", prog);
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+	pid_t pid = 0;
+	int vrf = 0;
+
+	extern char *optarg;
+	extern int optind;
+
+	while ((rc = getopt(argc, argv, "+:p:v:")) != -1) {
+		switch (rc) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'v':
+			vrf = atoi(optarg);
+			break;
+		default:
+			usage(argv[0]);
+			return 1;
+		}
+	}
+
+	if ((pid && vrf) || (!pid && !vrf)) {
+		usage(argv[0]);
+		return 1;
+	}
+
+	if (pid)
+		return show_vrf(pid);
+
+	if (optind == argc) {
+		usage(argv[0]);
+		return 1;
+	}
+
+	return run_vrf(&argv[optind], vrf);
+}
-- 
2.3.2 (Apple Git-55)

  parent reply	other threads:[~2015-07-27 18:33 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-27 18:30 [net-next 0/16] Proposal for VRF-lite - v3 David Ahern
2015-07-27 18:30 ` [PATCH net-next 01/16] net: Refactor rtable allocation and initialization David Ahern
2015-07-27 18:30 ` [PATCH net-next 02/16] net: export a few FIB functions David Ahern
2015-07-27 18:30 ` [PATCH net-next 03/16] net: Introduce VRF related flags and helpers David Ahern
2015-07-27 18:30 ` [PATCH net-next 04/16] net: Use VRF device index for lookups on RX David Ahern
2015-07-27 18:30 ` [PATCH net-next 05/16] net: Use VRF device index for lookups on TX David Ahern
2015-07-27 18:30 ` [PATCH net-next 06/16] net: Tx via VRF device David Ahern
2015-07-27 18:31 ` [PATCH net-next 07/16] net: Add inet_addr lookup by table David Ahern
2015-07-27 18:31 ` [PATCH net-next 08/16] net: Fix up inet_addr_type checks David Ahern
2015-07-27 18:31 ` [PATCH net-next 09/16] net: Add routes to the table associated with the device David Ahern
2015-07-27 18:31 ` [PATCH net-next 10/16] net: Use passed in table for nexthop lookups David Ahern
2015-07-27 18:31 ` [PATCH net-next 11/16] net: Use VRF device index for socket lookups David Ahern
2015-07-27 18:31 ` [PATCH net-next 12/16] net: Add ipv4 route helper to set next hop David Ahern
2015-07-27 18:31 ` [PATCH net-next 13/16] net: Introduce VRF device driver - v2 David Ahern
2015-07-27 20:01   ` Nikolay Aleksandrov
2015-07-28 16:22     ` David Ahern
2015-07-27 18:31 ` [PATCH net-next 14/16] net: Add sk_bind_dev_if to task_struct David Ahern
2015-07-27 20:33   ` Eric W. Biederman
2015-07-28 12:19     ` Hannes Frederic Sowa
2015-07-28 13:54       ` Eric W. Biederman
2015-07-28 14:20         ` Hannes Frederic Sowa
2015-07-28 16:01       ` Eric Dumazet
2015-07-28 16:07         ` David Ahern
2015-07-28 16:52           ` Eric Dumazet
2015-07-28 15:25   ` Andy Lutomirski
2015-07-28 16:11     ` David Ahern
2015-07-28 17:12       ` Tom Herbert
2015-07-27 18:31 ` David Ahern [this message]
2015-07-27 18:31 ` [PATCH] iproute2: Add support for VRF device David Ahern
2015-07-27 20:30 ` [net-next 0/16] Proposal for VRF-lite - v3 Eric W. Biederman
2015-07-28 16:02   ` David Ahern
2015-07-28 17:07     ` Eric W. Biederman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1438021869-49186-16-git-send-email-dsa@cumulusnetworks.com \
    --to=dsa@cumulusnetworks.com \
    --cc=davem@davemloft.net \
    --cc=ddutt@cumulusnetworks.com \
    --cc=ebiederm@xmission.com \
    --cc=gospo@cumulusnetworks.com \
    --cc=hadi@mojatatu.com \
    --cc=hannes@stressinduktion.org \
    --cc=jtoppins@cumulusnetworks.com \
    --cc=luto@amacapital.net \
    --cc=mingo@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=nicolas.dichtel@6wind.com \
    --cc=nikolay@cumulusnetworks.com \
    --cc=roopa@cumulusnetworks.com \
    --cc=shm@cumulusnetworks.com \
    --cc=stephen@networkplumber.org \
    --cc=svaidya@brocade.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).