struct tcp_congestion_ops *tcp_ca_find_key(u32 key);
 u32 tcp_ca_get_key_by_name(const char *name);
+#ifdef CONFIG_INET
 char *tcp_ca_get_name_by_key(u32 key, char *buffer);
+#else
+static inline char *tcp_ca_get_name_by_key(u32 key, char *buffer)
+{
+       return NULL;
+}
+#endif
 
 static inline bool tcp_ca_needs_ecn(const struct sock *sk)
 {
 
 #define RTAX_INITRWND RTAX_INITRWND
        RTAX_QUICKACK,
 #define RTAX_QUICKACK RTAX_QUICKACK
+       RTAX_CC_ALGO,
+#define RTAX_CC_ALGO RTAX_CC_ALGO
        __RTAX_MAX
 };
 
 
 #include <net/arp.h>
 #include <net/route.h>
 #include <net/udp.h>
+#include <net/tcp.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <net/fib_rules.h>
 
        for (i = 0; i < RTAX_MAX; i++) {
                if (metrics[i]) {
+                       if (i == RTAX_CC_ALGO - 1) {
+                               char tmp[TCP_CA_NAME_MAX], *name;
+
+                               name = tcp_ca_get_name_by_key(metrics[i], tmp);
+                               if (!name)
+                                       continue;
+                               if (nla_put_string(skb, i + 1, name))
+                                       goto nla_put_failure;
+                       } else {
+                               if (nla_put_u32(skb, i + 1, metrics[i]))
+                                       goto nla_put_failure;
+                       }
                        valid++;
-                       if (nla_put_u32(skb, i+1, metrics[i]))
-                               goto nla_put_failure;
                }
        }
 
 
                        int type = nla_type(attr);
 
                        if (type) {
-                               if (type > RTAX_MAX || nla_len(attr) < 4)
+                               if (type > RTAX_MAX || type == RTAX_CC_ALGO ||
+                                   nla_len(attr) < 4)
                                        goto err_inval;
 
                                fi->fib_metrics[type-1] = nla_get_u32(attr);
 
 #include <linux/route.h> /* RTF_xxx */
 #include <net/neighbour.h>
 #include <net/netlink.h>
+#include <net/tcp.h>
 #include <net/dst.h>
 #include <net/flow.h>
 #include <net/fib_rules.h>
        size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
                         + nla_total_size(4) /* RTA_TABLE */
                         + nla_total_size(2) /* RTA_DST */
-                        + nla_total_size(4); /* RTA_PRIORITY */
+                        + nla_total_size(4) /* RTA_PRIORITY */
+                        + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
 
        /* space for nested metrics */
        payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
 
                         + nla_total_size(4) /* RTA_TABLE */
                         + nla_total_size(4) /* RTA_DST */
                         + nla_total_size(4) /* RTA_PRIORITY */
-                        + nla_total_size(4); /* RTA_PREFSRC */
+                        + nla_total_size(4) /* RTA_PREFSRC */
+                        + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
 
        /* space for nested metrics */
        payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
 
                                if (type > RTAX_MAX)
                                        goto err_inval;
-                               val = nla_get_u32(nla);
+                               if (type == RTAX_CC_ALGO) {
+                                       char tmp[TCP_CA_NAME_MAX];
+
+                                       nla_strlcpy(tmp, nla, sizeof(tmp));
+                                       val = tcp_ca_get_key_by_name(tmp);
+                                       if (val == TCP_CA_UNSPEC)
+                                               goto err_inval;
+                               } else {
+                                       val = nla_get_u32(nla);
+                               }
                                if (type == RTAX_ADVMSS && val > 65535 - 40)
                                        val = 65535 - 40;
                                if (type == RTAX_MTU && val > 65535 - 15)
 
                int type = nla_type(nla);
 
                if (type) {
+                       u32 val;
+
                        if (unlikely(type > RTAX_MAX))
                                goto err;
+                       if (type == RTAX_CC_ALGO) {
+                               char tmp[TCP_CA_NAME_MAX];
+
+                               nla_strlcpy(tmp, nla, sizeof(tmp));
+                               val = tcp_ca_get_key_by_name(tmp);
+                               if (val == TCP_CA_UNSPEC)
+                                       goto err;
+                       } else {
+                               val = nla_get_u32(nla);
+                       }
 
-                       mp[type - 1] = nla_get_u32(nla);
+                       mp[type - 1] = val;
                        __set_bit(type - 1, mxc->mx_valid);
                }
        }
               + nla_total_size(4) /* RTA_OIF */
               + nla_total_size(4) /* RTA_PRIORITY */
               + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
-              + nla_total_size(sizeof(struct rta_cacheinfo));
+              + nla_total_size(sizeof(struct rta_cacheinfo))
+              + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
 }
 
 static int rt6_fill_node(struct net *net,