Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

openvswitch: Add timeout support to ct action

Add support for fine-grain timeout support to conntrack action.
The new OVS_CT_ATTR_TIMEOUT attribute of the conntrack action
specifies a timeout to be associated with this connection.
If no timeout is specified, it acts as is, that is the default
timeout for the connection will be automatically applied.

Example usage:
$ nfct timeout add timeout_1 inet tcp syn_sent 100 established 200
$ ovs-ofctl add-flow br0 in_port=1,ip,tcp,action=ct(commit,timeout=timeout_1)

CC: Pravin Shelar <pshelar@ovn.org>
CC: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yi-Hung Wei and committed by
David S. Miller
06bd2bdf 717700d1

+32 -1
+3
include/uapi/linux/openvswitch.h
··· 734 734 * be received on NFNLGRP_CONNTRACK_NEW and NFNLGRP_CONNTRACK_DESTROY groups, 735 735 * respectively. Remaining bits control the changes for which an event is 736 736 * delivered on the NFNLGRP_CONNTRACK_UPDATE group. 737 + * @OVS_CT_ATTR_TIMEOUT: Variable length string defining conntrack timeout. 737 738 */ 738 739 enum ovs_ct_attr { 739 740 OVS_CT_ATTR_UNSPEC, ··· 747 746 OVS_CT_ATTR_NAT, /* Nested OVS_NAT_ATTR_* */ 748 747 OVS_CT_ATTR_FORCE_COMMIT, /* No argument */ 749 748 OVS_CT_ATTR_EVENTMASK, /* u32 mask of IPCT_* events. */ 749 + OVS_CT_ATTR_TIMEOUT, /* Associate timeout with this connection for 750 + * fine-grain timeout tuning. */ 750 751 __OVS_CT_ATTR_MAX 751 752 }; 752 753
+29 -1
net/openvswitch/conntrack.c
··· 24 24 #include <net/netfilter/nf_conntrack_helper.h> 25 25 #include <net/netfilter/nf_conntrack_labels.h> 26 26 #include <net/netfilter/nf_conntrack_seqadj.h> 27 + #include <net/netfilter/nf_conntrack_timeout.h> 27 28 #include <net/netfilter/nf_conntrack_zones.h> 28 29 #include <net/netfilter/ipv6/nf_defrag_ipv6.h> 29 30 #include <net/ipv6_frag.h> ··· 74 73 u32 eventmask; /* Mask of 1 << IPCT_*. */ 75 74 struct md_mark mark; 76 75 struct md_labels labels; 76 + char timeout[CTNL_TIMEOUT_NAME_MAX]; 77 77 #ifdef CONFIG_NF_NAT_NEEDED 78 78 struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */ 79 79 #endif ··· 1473 1471 #endif 1474 1472 [OVS_CT_ATTR_EVENTMASK] = { .minlen = sizeof(u32), 1475 1473 .maxlen = sizeof(u32) }, 1474 + [OVS_CT_ATTR_TIMEOUT] = { .minlen = 1, 1475 + .maxlen = CTNL_TIMEOUT_NAME_MAX }, 1476 1476 }; 1477 1477 1478 1478 static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, ··· 1560 1556 info->have_eventmask = true; 1561 1557 info->eventmask = nla_get_u32(a); 1562 1558 break; 1559 + #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 1560 + case OVS_CT_ATTR_TIMEOUT: 1561 + memcpy(info->timeout, nla_data(a), nla_len(a)); 1562 + if (!memchr(info->timeout, '\0', nla_len(a))) { 1563 + OVS_NLERR(log, "Invalid conntrack helper"); 1564 + return -EINVAL; 1565 + } 1566 + break; 1567 + #endif 1563 1568 1564 1569 default: 1565 1570 OVS_NLERR(log, "Unknown conntrack attr (%d)", ··· 1650 1637 OVS_NLERR(log, "Failed to allocate conntrack template"); 1651 1638 return -ENOMEM; 1652 1639 } 1640 + 1641 + if (ct_info.timeout[0]) { 1642 + if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto, 1643 + ct_info.timeout)) 1644 + pr_info_ratelimited("Failed to associated timeout " 1645 + "policy `%s'\n", ct_info.timeout); 1646 + } 1647 + 1653 1648 if (helper) { 1654 1649 err = ovs_ct_add_helper(&ct_info, helper, key, log); 1655 1650 if (err) ··· 1778 1757 if (ct_info->have_eventmask && 1779 1758 nla_put_u32(skb, OVS_CT_ATTR_EVENTMASK, ct_info->eventmask)) 1780 1759 return -EMSGSIZE; 1760 + if (ct_info->timeout[0]) { 1761 + if (nla_put_string(skb, OVS_CT_ATTR_TIMEOUT, ct_info->timeout)) 1762 + return -EMSGSIZE; 1763 + } 1781 1764 1782 1765 #ifdef CONFIG_NF_NAT_NEEDED 1783 1766 if (ct_info->nat && !ovs_ct_nat_to_attr(ct_info, skb)) ··· 1803 1778 { 1804 1779 if (ct_info->helper) 1805 1780 nf_conntrack_helper_put(ct_info->helper); 1806 - if (ct_info->ct) 1781 + if (ct_info->ct) { 1807 1782 nf_ct_tmpl_free(ct_info->ct); 1783 + if (ct_info->timeout[0]) 1784 + nf_ct_destroy_timeout(ct_info->ct); 1785 + } 1808 1786 } 1809 1787 1810 1788 #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)