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)
Unified · Split
| @@ -734,6 +734,7 @@ struct ovs_action_hash { · 733 unmodified lines | ||
| 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, |
| @@ -746,6 +747,8 @@ enum ovs_ct_attr { · 6 unmodified lines | ||
| 746 | 747 | OVS_CT_ATTR_NAT, /* Nested OVS_NAT_ATTR_* */ |
| 747 | 748 | OVS_CT_ATTR_FORCE_COMMIT, /* No argument */ |
| 748 | 749 | OVS_CT_ATTR_EVENTMASK, /* u32 mask of IPCT_* events. */ |
| 750 | + OVS_CT_ATTR_TIMEOUT, /* Associate timeout with this connection for | |
| 751 | + * fine-grain timeout tuning. */ | |
| 749 | 752 | __OVS_CT_ATTR_MAX |
| 750 | 753 | }; |
| 751 | 754 | |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 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> |
| @@ -73,6 +74,7 @@ struct ovs_conntrack_info { · 43 unmodified lines | ||
| 73 | 74 | u32 eventmask; /* Mask of 1 << IPCT_*. */ |
| 74 | 75 | struct md_mark mark; |
| 75 | 76 | struct md_labels labels; |
| 77 | + char timeout[CTNL_TIMEOUT_NAME_MAX]; | |
| 76 | 78 | #ifdef CONFIG_NF_NAT_NEEDED |
| 77 | 79 | struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */ |
| 78 | 80 | #endif |
| @@ -1471,6 +1473,8 @@ static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = { · 1392 unmodified lines | ||
| 1471 | 1473 | #endif |
| 1472 | 1474 | [OVS_CT_ATTR_EVENTMASK] = { .minlen = sizeof(u32), |
| 1473 | 1475 | .maxlen = sizeof(u32) }, |
| 1476 | + [OVS_CT_ATTR_TIMEOUT] = { .minlen = 1, | |
| 1477 | + .maxlen = CTNL_TIMEOUT_NAME_MAX }, | |
| 1474 | 1478 | }; |
| 1475 | 1479 | |
| 1476 | 1480 | static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, |
| @@ -1556,6 +1560,15 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, · 79 unmodified lines | ||
| 1556 | 1560 | info->have_eventmask = true; |
| 1557 | 1561 | info->eventmask = nla_get_u32(a); |
| 1558 | 1562 | break; |
| 1563 | +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT | |
| 1564 | + case OVS_CT_ATTR_TIMEOUT: | |
| 1565 | + memcpy(info->timeout, nla_data(a), nla_len(a)); | |
| 1566 | + if (!memchr(info->timeout, '\0', nla_len(a))) { | |
| 1567 | + OVS_NLERR(log, "Invalid conntrack helper"); | |
| 1568 | + return -EINVAL; | |
| 1569 | + } | |
| 1570 | + break; | |
| 1571 | +#endif | |
| 1559 | 1572 | |
| 1560 | 1573 | default: |
| 1561 | 1574 | OVS_NLERR(log, "Unknown conntrack attr (%d)", |
| @@ -1637,6 +1650,14 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, · 75 unmodified lines | ||
| 1637 | 1650 | OVS_NLERR(log, "Failed to allocate conntrack template"); |
| 1638 | 1651 | return -ENOMEM; |
| 1639 | 1652 | } |
| 1653 | + | |
| 1654 | + if (ct_info.timeout[0]) { | |
| 1655 | + if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto, | |
| 1656 | + ct_info.timeout)) | |
| 1657 | + pr_info_ratelimited("Failed to associated timeout " | |
| 1658 | + "policy `%s'\n", ct_info.timeout); | |
| 1659 | + } | |
| 1660 | + | |
| 1640 | 1661 | if (helper) { |
| 1641 | 1662 | err = ovs_ct_add_helper(&ct_info, helper, key, log); |
| 1642 | 1663 | if (err) |
| @@ -1757,6 +1778,10 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info, · 114 unmodified lines | ||
| 1757 | 1778 | if (ct_info->have_eventmask && |
| 1758 | 1779 | nla_put_u32(skb, OVS_CT_ATTR_EVENTMASK, ct_info->eventmask)) |
| 1759 | 1780 | return -EMSGSIZE; |
| 1781 | + if (ct_info->timeout[0]) { | |
| 1782 | + if (nla_put_string(skb, OVS_CT_ATTR_TIMEOUT, ct_info->timeout)) | |
| 1783 | + return -EMSGSIZE; | |
| 1784 | + } | |
| 1760 | 1785 | |
| 1761 | 1786 | #ifdef CONFIG_NF_NAT_NEEDED |
| 1762 | 1787 | if (ct_info->nat && !ovs_ct_nat_to_attr(ct_info, skb)) |
| @@ -1778,8 +1803,11 @@ static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info) · 15 unmodified lines | ||
| 1778 | 1803 | { |
| 1779 | 1804 | if (ct_info->helper) |
| 1780 | 1805 | nf_conntrack_helper_put(ct_info->helper); |
| 1781 | − if (ct_info->ct) | |
| 1806 | + if (ct_info->ct) { | |
| 1782 | 1807 | nf_ct_tmpl_free(ct_info->ct); |
| 1808 | + if (ct_info->timeout[0]) | |
| 1809 | + nf_ct_destroy_timeout(ct_info->ct); | |
| 1810 | + } | |
| 1783 | 1811 | } |
| 1784 | 1812 | |
| 1785 | 1813 | #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT) |