]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
xfrm: add an interface to offload policy
authorLeon Romanovsky <leonro@nvidia.com>
Mon, 12 Dec 2022 07:54:06 +0000 (09:54 +0200)
committerDavid Ahern <dsahern@kernel.org>
Wed, 14 Dec 2022 16:02:34 +0000 (09:02 -0700)
Extend at "ip xfrm policy" to allow policy offload to specific device.
The syntax and the code follow already established pattern from the
state offload.

The only difference between them is that direction was already mandatory
argument in policy configuration commands, so don't need to add direction
handling logic like it was done for the state offload.

The syntax is as follows:
 $ ip xfrm policy .... offload packet dev <if-name>

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
ip/ipxfrm.c
ip/xfrm.h
ip/xfrm_monitor.c
ip/xfrm_policy.c
man/man8/ip-xfrm.8

index deb45817aebc087aba2d74fd0596ed07b86613e2..7a1ebc9539b35135d83d7006a4871c59f1adbcd8 100644 (file)
@@ -688,8 +688,8 @@ done:
        return 0;
 }
 
-void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
-                     FILE *fp, const char *prefix, bool nokeys)
+void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, FILE *fp,
+                     const char *prefix, bool nokeys, bool dir)
 {
        if (tb[XFRMA_MARK]) {
                struct rtattr *rta = tb[XFRMA_MARK];
@@ -895,9 +895,12 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
 
                xuo = (struct xfrm_user_offload *)
                        RTA_DATA(tb[XFRMA_OFFLOAD_DEV]);
-               fprintf(fp, "dev %s dir %s mode %s",
-                       ll_index_to_name(xuo->ifindex),
-                       (xuo->flags & XFRM_OFFLOAD_INBOUND) ? "in" : "out",
+               fprintf(fp, "dev %s ",
+                       ll_index_to_name(xuo->ifindex));
+               if (dir)
+                       fprintf(fp, "dir %s ",
+                       (xuo->flags & XFRM_OFFLOAD_INBOUND) ? "in" : "out");
+               fprintf(fp, "mode %s",
                        (xuo->flags & XFRM_OFFLOAD_PACKET) ? "packet" : "crypto");
                fprintf(fp, "%s", _SL_);
        }
@@ -990,7 +993,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
                fprintf(fp, " (0x%s)", strxf_mask8(xsinfo->flags));
        fprintf(fp, "%s", _SL_);
 
-       xfrm_xfrma_print(tb, xsinfo->family, fp, buf, nokeys);
+       xfrm_xfrma_print(tb, xsinfo->family, fp, buf, nokeys, true);
 
        if (!xfrm_selector_iszero(&xsinfo->sel)) {
                char sbuf[STRBUF_SIZE];
@@ -1096,7 +1099,7 @@ void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo,
        if (show_stats > 0)
                xfrm_lifetime_print(&xpinfo->lft, &xpinfo->curlft, fp, buf);
 
-       xfrm_xfrma_print(tb, xpinfo->sel.family, fp, buf, false);
+       xfrm_xfrma_print(tb, xpinfo->sel.family, fp, buf, false, false);
 }
 
 int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family,
index 17dcf3fea83f207cd8a6619440e0ef0927475b54..6f251603f1082ad492ab9f47ed2d572f5fe03aef 100644 (file)
--- a/ip/xfrm.h
+++ b/ip/xfrm.h
@@ -124,8 +124,8 @@ const char *strxf_proto(__u8 proto);
 const char *strxf_ptype(__u8 ptype);
 void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,
                         FILE *fp, const char *prefix);
-void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
-                     FILE *fp, const char *prefix, bool nokeys);
+void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, FILE *fp,
+                     const char *prefix, bool nokeys, bool dir);
 void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
                            struct rtattr *tb[], FILE *fp, const char *prefix,
                           const char *title, bool nokeys);
index f67424c5be0699af6587aa1fbddaca7863045dee..b0056d9de43244e20f4b463e726a61edb3335e7e 100644 (file)
@@ -199,7 +199,7 @@ static int xfrm_report_print(struct nlmsghdr *n, void *arg)
 
        parse_rtattr(tb, XFRMA_MAX, XFRMREP_RTA(xrep), len);
 
-       xfrm_xfrma_print(tb, family, fp, "  ", nokeys);
+       xfrm_xfrma_print(tb, family, fp, "  ", nokeys, true);
 
        if (oneline)
                fprintf(fp, "\n");
index 4d825025cb69872a3e6fce61d58708f82d4fcc29..be5fcfed2027f69d1bd1d9c63f0338639fee89ed 100644 (file)
@@ -57,6 +57,7 @@ static void usage(void)
                "       [ mark MARK [ mask MASK ] ] [ index INDEX ] [ ptype PTYPE ]\n"
                "       [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ]\n"
                "       [ if_id IF_ID ] [ LIMIT-LIST ] [ TMPL-LIST ]\n"
+               "       [ offload packet dev DEV] } ]\n"
                "Usage: ip xfrm policy { delete | get } { SELECTOR | index INDEX } dir DIR\n"
                "       [ ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]\n"
                "       [ if_id IF_ID ]\n"
@@ -260,6 +261,7 @@ static int xfrm_policy_modify(int cmd, unsigned int flags, int argc, char **argv
        char *ptypep = NULL;
        char *sctxp = NULL;
        struct xfrm_userpolicy_type upt = {};
+       struct xfrm_user_offload xuo = {};
        char tmpls_buf[XFRM_TMPLS_BUF_SIZE] = {};
        int tmpls_len = 0;
        struct xfrm_mark mark = {0, 0};
@@ -268,6 +270,8 @@ static int xfrm_policy_modify(int cmd, unsigned int flags, int argc, char **argv
                char    str[CTX_BUF_SIZE];
        } ctx = {};
        bool is_if_id_set = false;
+       unsigned int ifindex = 0;
+       bool is_offload = false;
        __u32 if_id = 0;
 
        while (argc > 0) {
@@ -342,6 +346,21 @@ static int xfrm_policy_modify(int cmd, unsigned int flags, int argc, char **argv
                        if (get_u32(&if_id, *argv, 0))
                                invarg("IF_ID value is invalid", *argv);
                        is_if_id_set = true;
+               } else if (strcmp(*argv, "offload") == 0) {
+                       NEXT_ARG();
+                       if (strcmp(*argv, "packet") == 0)
+                               NEXT_ARG();
+                       else
+                               invarg("Invalid offload mode", *argv);
+
+                       if (strcmp(*argv, "dev") == 0) {
+                               NEXT_ARG();
+                               ifindex = ll_name_to_index(*argv);
+                               if (!ifindex)
+                                       invarg("Invalid device name", *argv);
+                       } else
+                               invarg("Missing dev keyword", *argv);
+                       is_offload = true;
                } else {
                        if (selp)
                                duparg("unknown", *argv);
@@ -387,6 +406,13 @@ static int xfrm_policy_modify(int cmd, unsigned int flags, int argc, char **argv
        if (is_if_id_set)
                addattr32(&req.n, sizeof(req.buf), XFRMA_IF_ID, if_id);
 
+       if (is_offload) {
+               xuo.ifindex = ifindex;
+               xuo.flags |= XFRM_OFFLOAD_PACKET;
+               addattr_l(&req.n, sizeof(req.buf), XFRMA_OFFLOAD_DEV, &xuo,
+                         sizeof(xuo));
+       }
+
        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
                exit(1);
 
index a65cfa5f49b85313b7dbf9be211687848c85b97f..3270f336d0706f951bdfa45bc5b7bfe8d7cfacf0 100644 (file)
@@ -252,6 +252,10 @@ ip-xfrm \- transform configuration
 .IR FLAG-LIST " ]"
 .RB "[ " if_id
 .IR IF-ID " ]"
+.RB "[ " offload
+.RB packet
+.RB dev
+.IR DEV " ]"
 .RI "[ " LIMIT-LIST " ] [ " TMPL-LIST " ]"
 
 .ti -8
@@ -593,6 +597,10 @@ of the packets emitted by the state
 .I IF-ID
 xfrm interface identifier used to in both xfrm policies and states
 
+.TP
+.I DEV
+Network interface name used to offload policies and states
+
 .sp
 .PP
 .TS