This commit was generated by cvs2svn to compensate for changes in r2587,
[iproute2.git] / ip / iproute.c
index 1e23e49..a43c09e 100644 (file)
@@ -28,6 +28,7 @@
 #include <netinet/ip.h>
 #include <arpa/inet.h>
 #include <linux/in_route.h>
+#include <linux/ip_mp_alg.h>
 
 #include "rt_names.h"
 #include "utils.h"
@@ -53,6 +54,7 @@ static void usage(void)
        fprintf(stderr, "NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ]\n");
        fprintf(stderr, "             [ table TABLE_ID ] [ proto RTPROTO ]\n");
        fprintf(stderr, "             [ scope SCOPE ] [ metric METRIC ]\n");
+       fprintf(stderr, "             [ mpath MP_ALGO ]\n");
        fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n");
        fprintf(stderr, "NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
        fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n");
@@ -64,6 +66,7 @@ static void usage(void)
        fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n");
        fprintf(stderr, "SCOPE := [ host | link | global | NUMBER ]\n");
        fprintf(stderr, "FLAGS := [ equalize ]\n");
+       fprintf(stderr, "MP_ALGO := { rr | drr | random | wrandom }\n");
        fprintf(stderr, "NHFLAGS := [ onlink | pervasive ]\n");
        fprintf(stderr, "RTPROTO := [ kernel | boot | static | NUMBER ]\n");
        exit(-1);
@@ -77,7 +80,6 @@ static struct
        char *flushb;
        int flushp;
        int flushe;
-       struct rtnl_handle *rth;
        int protocol, protocolmask;
        int scope, scopemask;
        int type, typemask;
@@ -93,9 +95,17 @@ static struct
        inet_prefix msrc;
 } filter;
 
+static char *mp_alg_names[IP_MP_ALG_MAX+1] = {
+       [IP_MP_ALG_NONE] = "none",
+       [IP_MP_ALG_RR] = "rr",
+       [IP_MP_ALG_DRR] = "drr",
+       [IP_MP_ALG_RANDOM] = "random",
+       [IP_MP_ALG_WRANDOM] = "wrandom"
+};
+
 static int flush_update(void)
 {
-       if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
+       if (rtnl_send(&rth, filter.flushb, filter.flushp) < 0) {
                perror("Failed to send flush request\n");
                return -1;
        }
@@ -206,13 +216,13 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
                memset(&via, 0, sizeof(via));
                via.family = r->rtm_family;
                if (tb[RTA_GATEWAY])
-                       memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len);
+                       memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len/8);
        }
        if (filter.rprefsrc.bitlen>0) {
                memset(&prefsrc, 0, sizeof(prefsrc));
                prefsrc.family = r->rtm_family;
                if (tb[RTA_PREFSRC])
-                       memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len);
+                       memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len/8);
        }
 
        if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen))
@@ -270,7 +280,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
                memcpy(fn, n, n->nlmsg_len);
                fn->nlmsg_type = RTM_DELROUTE;
                fn->nlmsg_flags = NLM_F_REQUEST;
-               fn->nlmsg_seq = ++filter.rth->seq;
+               fn->nlmsg_seq = ++rth.seq;
                filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
                filter.flushed++;
                if (show_stats < 2)
@@ -324,6 +334,15 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
                SPRINT_BUF(b1);
                fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1)));
        }
+
+       if (tb[RTA_MP_ALGO]) {
+               __u32 mp_alg = *(__u32*) RTA_DATA(tb[RTA_MP_ALGO]);
+               if (mp_alg > IP_MP_ALG_NONE) {
+                       fprintf(fp, "mpath %s ",
+                           mp_alg < IP_MP_ALG_MAX ? mp_alg_names[mp_alg] : "unknown");
+               }
+       }
+
        if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) {
                fprintf(fp, "via %s ", 
                        format_host(r->rtm_family,
@@ -616,9 +635,6 @@ int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, int argc, char **argv)
                }
                memset(rtnh, 0, sizeof(*rtnh));
                rtnh->rtnh_len = sizeof(*rtnh);
-               rtnh->rtnh_ifindex = 0;
-               rtnh->rtnh_flags = 0;
-               rtnh->rtnh_hops = 0;
                rta->rta_len += rtnh->rtnh_len;
                parse_one_nh(rta, rtnh, &argc, &argv);
                rtnh = RTNH_NEXT(rtnh);
@@ -632,7 +648,6 @@ int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, int argc, char **argv)
 
 int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
 {
-       struct rtnl_handle rth;
        struct {
                struct nlmsghdr         n;
                struct rtmsg            r;
@@ -709,7 +724,7 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
                                invarg("\"metric\" value is invalid\n", *argv);
                        addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric);
                } else if (strcmp(*argv, "scope") == 0) {
-                       int scope = 0;
+                       __u32 scope = 0;
                        NEXT_ARG();
                        if (rtnl_rtscope_a2n(&scope, *argv))
                                invarg("invalid \"scope\" value\n", *argv);
@@ -814,14 +829,14 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
                        nhs_ok = 1;
                        break;
                } else if (matches(*argv, "protocol") == 0) {
-                       int prot;
+                       __u32 prot;
                        NEXT_ARG();
                        if (rtnl_rtprot_a2n(&prot, *argv))
                                invarg("\"protocol\" value is invalid\n", *argv);
                        req.r.rtm_protocol = prot;
                        proto_ok =1;
                } else if (matches(*argv, "table") == 0) {
-                       int tid;
+                       __u32 tid;
                        NEXT_ARG();
                        if (rtnl_rttable_a2n(&tid, *argv))
                                invarg("\"table\" value is invalid\n", *argv);
@@ -831,6 +846,18 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
                           strcmp(*argv, "oif") == 0) {
                        NEXT_ARG();
                        d = *argv;
+               } else if (strcmp(*argv, "mpath") == 0 ||
+                          strcmp(*argv, "mp") == 0) {
+                       int i;
+                       __u32 mp_alg = IP_MP_ALG_NONE;
+
+                       NEXT_ARG();
+                       for (i = 1; i < ARRAY_SIZE(mp_alg_names); i++)
+                               if (strcmp(*argv, mp_alg_names[i]) == 0)
+                                       mp_alg = i;
+                       if (mp_alg == IP_MP_ALG_NONE)
+                               invarg("\"mpath\" value is invalid\n", *argv);
+                       addattr_l(&req.n, sizeof(req), RTA_MP_ALGO, &mp_alg, sizeof(mp_alg));
                } else {
                        int type;
                        inet_prefix dst;
@@ -860,9 +887,6 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
                argc--; argv++;
        }
 
-       if (rtnl_open(&rth, 0) < 0)
-               exit(1);
-
        if (d || nhs_ok)  {
                int idx;
 
@@ -969,7 +993,6 @@ static int iproute_flush_cache(void)
 static int iproute_list_or_flush(int argc, char **argv, int flush)
 {
        int do_ipv6 = preferred_family;
-       struct rtnl_handle rth;
        char *id = NULL;
        char *od = NULL;
 
@@ -983,7 +1006,7 @@ static int iproute_list_or_flush(int argc, char **argv, int flush)
 
        while (argc > 0) {
                if (matches(*argv, "table") == 0) {
-                       int tid;
+                       __u32 tid;
                        NEXT_ARG();
                        if (rtnl_rttable_a2n(&tid, *argv)) {
                                if (strcmp(*argv, "all") == 0) {
@@ -1009,7 +1032,7 @@ static int iproute_list_or_flush(int argc, char **argv, int flush)
                        filter.tos = tos;
                        filter.tosmask = -1;
                } else if (matches(*argv, "protocol") == 0) {
-                       int prot = 0;
+                       __u32 prot = 0;
                        NEXT_ARG();
                        filter.protocolmask = -1;
                        if (rtnl_rtprot_a2n(&prot, *argv)) {
@@ -1020,7 +1043,7 @@ static int iproute_list_or_flush(int argc, char **argv, int flush)
                        }
                        filter.protocol = prot;
                } else if (matches(*argv, "scope") == 0) {
-                       int scope = 0;
+                       __u32 scope = 0;
                        NEXT_ARG();
                        filter.scopemask = -1;
                        if (rtnl_rtscope_a2n(&scope, *argv)) {
@@ -1103,9 +1126,6 @@ static int iproute_list_or_flush(int argc, char **argv, int flush)
        if (do_ipv6 == AF_UNSPEC && filter.tb)
                do_ipv6 = AF_INET;
 
-       if (rtnl_open(&rth, 0) < 0)
-               exit(1);
-
        ll_init_map(&rth);
 
        if (id || od)  {
@@ -1147,7 +1167,6 @@ static int iproute_list_or_flush(int argc, char **argv, int flush)
                filter.flushb = flushb;
                filter.flushp = 0;
                filter.flushe = sizeof(flushb);
-               filter.rth = &rth;
 
                for (;;) {
                        if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
@@ -1208,7 +1227,6 @@ static int iproute_list_or_flush(int argc, char **argv, int flush)
 
 int iproute_get(int argc, char **argv)
 {
-       struct rtnl_handle rth;
        struct {
                struct nlmsghdr         n;
                struct rtmsg            r;
@@ -1288,9 +1306,6 @@ int iproute_get(int argc, char **argv)
                exit(1);
        }
 
-       if (rtnl_open(&rth, 0) < 0)
-               exit(1);
-
        ll_init_map(&rth);
 
        if (idev || odev)  {