Import of kernel-4.18.0-553.134.1.el8_10
This commit is contained in:
parent
1f10fa954f
commit
a8926071b0
@ -12,7 +12,7 @@ RHEL_MINOR = 10
|
||||
#
|
||||
# Use this spot to avoid future merge conflicts.
|
||||
# Do not trim this comment.
|
||||
RHEL_RELEASE = 553.132.1
|
||||
RHEL_RELEASE = 553.134.1
|
||||
|
||||
#
|
||||
# ZSTREAM
|
||||
|
||||
@ -151,6 +151,11 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||
bphy_err(drvr, "invalid interface index: %u\n", ifevent->ifidx);
|
||||
return;
|
||||
}
|
||||
if (ifevent->bsscfgidx >= BRCMF_MAX_IFS) {
|
||||
bphy_err(drvr, "invalid bsscfg index: %u\n",
|
||||
ifevent->bsscfgidx);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[ifevent->bsscfgidx];
|
||||
|
||||
|
||||
@ -933,6 +933,12 @@ static void privcmd_close(struct vm_area_struct *vma)
|
||||
kfree(pages);
|
||||
}
|
||||
|
||||
static int privcmd_may_split(struct vm_area_struct *area, unsigned long addr)
|
||||
{
|
||||
/* Forbid splitting, avoids double free via privcmd_close(). */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static vm_fault_t privcmd_fault(struct vm_fault *vmf)
|
||||
{
|
||||
printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n",
|
||||
@ -944,6 +950,7 @@ static vm_fault_t privcmd_fault(struct vm_fault *vmf)
|
||||
|
||||
static const struct vm_operations_struct privcmd_vm_ops = {
|
||||
.close = privcmd_close,
|
||||
.split = privcmd_may_split,
|
||||
.fault = privcmd_fault
|
||||
};
|
||||
|
||||
|
||||
@ -367,6 +367,8 @@ static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer)
|
||||
ret = sprintf(buffer, "<denied>");
|
||||
return ret;
|
||||
}
|
||||
if (ret > PAGE_SIZE)
|
||||
return -ENOSPC;
|
||||
|
||||
buildid = kmalloc(sizeof(*buildid) + ret, GFP_KERNEL);
|
||||
if (!buildid)
|
||||
@ -374,8 +376,10 @@ static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer)
|
||||
|
||||
buildid->len = ret;
|
||||
ret = HYPERVISOR_xen_version(XENVER_build_id, buildid);
|
||||
if (ret > 0)
|
||||
ret = sprintf(buffer, "%s", buildid->buf);
|
||||
if (ret > 0) {
|
||||
/* Build id is binary, not a string. */
|
||||
memcpy(buffer, buildid->buf, ret);
|
||||
}
|
||||
kfree(buildid);
|
||||
|
||||
return ret;
|
||||
|
||||
@ -67,6 +67,16 @@ struct nft_flow_rule {
|
||||
struct flow_rule *rule;
|
||||
};
|
||||
|
||||
static inline struct flow_action_entry *
|
||||
nft_flow_action_entry_next(struct nft_offload_ctx *ctx,
|
||||
struct nft_flow_rule *flow)
|
||||
{
|
||||
if (unlikely(ctx->num_actions >= flow->rule->action.num_entries))
|
||||
return NULL;
|
||||
|
||||
return &flow->rule->action.entries[ctx->num_actions++];
|
||||
}
|
||||
|
||||
void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
|
||||
enum flow_dissector_key_id addr_type);
|
||||
|
||||
|
||||
@ -5367,9 +5367,11 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data,
|
||||
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
|
||||
if (!conn)
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
conn->passkey_notify = __le32_to_cpu(ev->passkey);
|
||||
conn->passkey_entered = 0;
|
||||
@ -5378,6 +5380,9 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data,
|
||||
mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, conn->passkey_notify,
|
||||
conn->passkey_entered);
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data,
|
||||
@ -5388,14 +5393,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data,
|
||||
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
|
||||
if (!conn)
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
switch (ev->type) {
|
||||
case HCI_KEYPRESS_STARTED:
|
||||
conn->passkey_entered = 0;
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
case HCI_KEYPRESS_ENTERED:
|
||||
conn->passkey_entered++;
|
||||
@ -5410,13 +5417,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data,
|
||||
break;
|
||||
|
||||
case HCI_KEYPRESS_COMPLETED:
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (hci_dev_test_flag(hdev, HCI_MGMT))
|
||||
mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, conn->passkey_notify,
|
||||
conn->passkey_entered);
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data,
|
||||
|
||||
@ -6615,7 +6615,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_bss *bss = (void *)cbss->priv;
|
||||
struct sta_info *new_sta = NULL;
|
||||
struct ieee80211_link_data *link;
|
||||
bool have_sta = false;
|
||||
struct sta_info *have_sta = NULL;
|
||||
bool mlo;
|
||||
int err;
|
||||
|
||||
@ -6653,11 +6653,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (assoc) {
|
||||
rcu_read_lock();
|
||||
if (assoc)
|
||||
have_sta = sta_info_get(sdata, ap_mld_addr);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (!have_sta) {
|
||||
if (mlo)
|
||||
@ -6780,6 +6777,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
out_err:
|
||||
ieee80211_link_release_channel(&sdata->deflink);
|
||||
if (mlo && have_sta)
|
||||
WARN_ON(__sta_info_destroy(have_sta));
|
||||
ieee80211_vif_set_links(sdata, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -4774,7 +4774,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
|
||||
struct sk_buff *skb = rx->skb;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
static ieee80211_rx_result res;
|
||||
ieee80211_rx_result res;
|
||||
int orig_len = skb->len;
|
||||
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
int snap_offs = hdrlen;
|
||||
|
||||
@ -3714,6 +3714,8 @@ int __init mptcp_proto_v6_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
mptcp_subflow_v6_init();
|
||||
|
||||
mptcp_v6_prot = mptcp_prot;
|
||||
strcpy(mptcp_v6_prot.name, "MPTCPv6");
|
||||
mptcp_v6_prot.slab = NULL;
|
||||
|
||||
@ -603,6 +603,7 @@ static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
|
||||
void __init mptcp_proto_init(void);
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
int __init mptcp_proto_v6_init(void);
|
||||
void __init mptcp_subflow_v6_init(void);
|
||||
#endif
|
||||
|
||||
struct sock *mptcp_sk_clone(const struct sock *sk,
|
||||
|
||||
@ -1766,7 +1766,15 @@ void __init mptcp_subflow_init(void)
|
||||
tcp_prot_override = tcp_prot;
|
||||
tcp_prot_override.release_cb = tcp_release_cb_override;
|
||||
|
||||
mptcp_diag_subflow_init(&subflow_ulp_ops);
|
||||
|
||||
if (tcp_register_ulp(&subflow_ulp_ops) != 0)
|
||||
panic("MPTCP: failed to register subflows to ULP\n");
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
void __init mptcp_subflow_v6_init(void)
|
||||
{
|
||||
subflow_request_sock_ipv6_ops = tcp_request_sock_ipv6_ops;
|
||||
subflow_request_sock_ipv6_ops.route_req = subflow_v6_route_req;
|
||||
|
||||
@ -1784,10 +1792,5 @@ void __init mptcp_subflow_init(void)
|
||||
|
||||
tcpv6_prot_override = tcpv6_prot;
|
||||
tcpv6_prot_override.release_cb = tcp_release_cb_override;
|
||||
#endif
|
||||
|
||||
mptcp_diag_subflow_init(&subflow_ulp_ops);
|
||||
|
||||
if (tcp_register_ulp(&subflow_ulp_ops) != 0)
|
||||
panic("MPTCP: failed to register subflows to ULP\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -67,7 +67,10 @@ int nft_fwd_dup_netdev_offload(struct nft_offload_ctx *ctx,
|
||||
if (!dev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
entry = &flow->rule->action.entries[ctx->num_actions++];
|
||||
entry = nft_flow_action_entry_next(ctx, flow);
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
entry->id = id;
|
||||
entry->dev = dev;
|
||||
|
||||
|
||||
@ -13,6 +13,8 @@
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_tuple.h>
|
||||
|
||||
#define NF_FLOW_RULE_ACTION_MAX 24
|
||||
|
||||
static struct workqueue_struct *nf_flow_offload_add_wq;
|
||||
static struct workqueue_struct *nf_flow_offload_del_wq;
|
||||
static struct workqueue_struct *nf_flow_offload_stats_wq;
|
||||
@ -167,7 +169,12 @@ static void flow_offload_mangle(struct flow_action_entry *entry,
|
||||
static inline struct flow_action_entry *
|
||||
flow_action_entry_next(struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
int i = flow_rule->rule->action.num_entries++;
|
||||
int i;
|
||||
|
||||
if (unlikely(flow_rule->rule->action.num_entries >= NF_FLOW_RULE_ACTION_MAX))
|
||||
return NULL;
|
||||
|
||||
i = flow_rule->rule->action.num_entries++;
|
||||
|
||||
return &flow_rule->rule->action.entries[i];
|
||||
}
|
||||
@ -184,6 +191,9 @@ static int flow_offload_eth_src(struct net *net,
|
||||
u32 mask, val;
|
||||
u16 val16;
|
||||
|
||||
if (!entry0 || !entry1)
|
||||
return -E2BIG;
|
||||
|
||||
dev = dev_get_by_index(net, tuple->iifidx);
|
||||
if (!dev)
|
||||
return -ENOENT;
|
||||
@ -218,6 +228,9 @@ static int flow_offload_eth_dst(struct net *net,
|
||||
u8 nud_state;
|
||||
u16 val16;
|
||||
|
||||
if (!entry0 || !entry1)
|
||||
return -E2BIG;
|
||||
|
||||
dst_cache = flow->tuplehash[dir].tuple.dst_cache;
|
||||
n = dst_neigh_lookup(dst_cache, daddr);
|
||||
if (!n)
|
||||
@ -248,16 +261,19 @@ static int flow_offload_eth_dst(struct net *net,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_ipv4_snat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_ipv4_snat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
u32 mask = ~htonl(0xffffffff);
|
||||
__be32 addr;
|
||||
u32 offset;
|
||||
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
switch (dir) {
|
||||
case FLOW_OFFLOAD_DIR_ORIGINAL:
|
||||
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr;
|
||||
@ -268,23 +284,27 @@ static void flow_offload_ipv4_snat(struct net *net,
|
||||
offset = offsetof(struct iphdr, daddr);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
|
||||
&addr, &mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_ipv4_dnat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_ipv4_dnat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
u32 mask = ~htonl(0xffffffff);
|
||||
__be32 addr;
|
||||
u32 offset;
|
||||
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
switch (dir) {
|
||||
case FLOW_OFFLOAD_DIR_ORIGINAL:
|
||||
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr;
|
||||
@ -295,14 +315,15 @@ static void flow_offload_ipv4_dnat(struct net *net,
|
||||
offset = offsetof(struct iphdr, saddr);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
|
||||
&addr, &mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
|
||||
static int flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
|
||||
unsigned int offset,
|
||||
const __be32 *addr, const __be32 *mask)
|
||||
{
|
||||
@ -311,15 +332,20 @@ static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
|
||||
|
||||
for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i++) {
|
||||
entry = flow_action_entry_next(flow_rule);
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6,
|
||||
offset + i * sizeof(u32), &addr[i], mask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_ipv6_snat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_ipv6_snat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
u32 mask = ~htonl(0xffffffff);
|
||||
const __be32 *addr;
|
||||
@ -335,16 +361,16 @@ static void flow_offload_ipv6_snat(struct net *net,
|
||||
offset = offsetof(struct ipv6hdr, daddr);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
|
||||
return flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
|
||||
}
|
||||
|
||||
static void flow_offload_ipv6_dnat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_ipv6_dnat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
u32 mask = ~htonl(0xffffffff);
|
||||
const __be32 *addr;
|
||||
@ -360,10 +386,10 @@ static void flow_offload_ipv6_dnat(struct net *net,
|
||||
offset = offsetof(struct ipv6hdr, saddr);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
|
||||
return flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
|
||||
}
|
||||
|
||||
static int flow_offload_l4proto(const struct flow_offload *flow)
|
||||
@ -385,15 +411,18 @@ static int flow_offload_l4proto(const struct flow_offload *flow)
|
||||
return type;
|
||||
}
|
||||
|
||||
static void flow_offload_port_snat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_port_snat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
u32 mask, port;
|
||||
u32 offset;
|
||||
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
switch (dir) {
|
||||
case FLOW_OFFLOAD_DIR_ORIGINAL:
|
||||
port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
|
||||
@ -408,22 +437,26 @@ static void flow_offload_port_snat(struct net *net,
|
||||
mask = ~htonl(0xffff);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
|
||||
&port, &mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_port_dnat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_port_dnat(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
u32 mask, port;
|
||||
u32 offset;
|
||||
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
switch (dir) {
|
||||
case FLOW_OFFLOAD_DIR_ORIGINAL:
|
||||
port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port);
|
||||
@ -438,20 +471,24 @@ static void flow_offload_port_dnat(struct net *net,
|
||||
mask = ~htonl(0xffff0000);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
|
||||
&port, &mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_ipv4_checksum(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_ipv4_checksum(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
u8 protonum = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l4proto;
|
||||
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
entry->id = FLOW_ACTION_CSUM;
|
||||
entry->csum_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR;
|
||||
|
||||
@ -463,24 +500,30 @@ static void flow_offload_ipv4_checksum(struct net *net,
|
||||
entry->csum_flags |= TCA_CSUM_UPDATE_FLAG_UDP;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_redirect(const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_redirect(const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
struct rtable *rt;
|
||||
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache;
|
||||
entry->id = FLOW_ACTION_REDIRECT;
|
||||
entry->dev = rt->dst.dev;
|
||||
dev_hold(rt->dst.dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_encap_tunnel(const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_encap_tunnel(const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
struct flow_action_entry *entry;
|
||||
struct dst_entry *dst;
|
||||
@ -492,15 +535,19 @@ static void flow_offload_encap_tunnel(const struct flow_offload *flow,
|
||||
tun_info = lwt_tun_info(dst->lwtstate);
|
||||
if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX)) {
|
||||
entry = flow_action_entry_next(flow_rule);
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
entry->id = FLOW_ACTION_TUNNEL_ENCAP;
|
||||
entry->tunnel = tun_info;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flow_offload_decap_tunnel(const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
static int flow_offload_decap_tunnel(const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
struct flow_action_entry *entry;
|
||||
struct dst_entry *dst;
|
||||
@ -512,35 +559,44 @@ static void flow_offload_decap_tunnel(const struct flow_offload *flow,
|
||||
tun_info = lwt_tun_info(dst->lwtstate);
|
||||
if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX)) {
|
||||
entry = flow_action_entry_next(flow_rule);
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
entry->id = FLOW_ACTION_TUNNEL_DECAP;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
flow_offload_decap_tunnel(flow, dir, flow_rule);
|
||||
flow_offload_encap_tunnel(flow, dir, flow_rule);
|
||||
if (flow_offload_decap_tunnel(flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_encap_tunnel(flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
|
||||
if (flow_offload_eth_src(net, flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_eth_dst(net, flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
|
||||
if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
||||
flow_offload_ipv4_snat(net, flow, dir, flow_rule);
|
||||
flow_offload_port_snat(net, flow, dir, flow_rule);
|
||||
if (flow_offload_ipv4_snat(net, flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_port_snat(net, flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
}
|
||||
if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
|
||||
flow_offload_ipv4_dnat(net, flow, dir, flow_rule);
|
||||
flow_offload_port_dnat(net, flow, dir, flow_rule);
|
||||
if (flow_offload_ipv4_dnat(net, flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_port_dnat(net, flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
}
|
||||
if (test_bit(NF_FLOW_SNAT, &flow->flags) ||
|
||||
test_bit(NF_FLOW_DNAT, &flow->flags))
|
||||
flow_offload_ipv4_checksum(net, flow, flow_rule);
|
||||
if (flow_offload_ipv4_checksum(net, flow, flow_rule) < 0)
|
||||
return -1;
|
||||
|
||||
flow_offload_redirect(flow, dir, flow_rule);
|
||||
if (flow_offload_redirect(flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -550,30 +606,32 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule)
|
||||
{
|
||||
flow_offload_decap_tunnel(flow, dir, flow_rule);
|
||||
flow_offload_encap_tunnel(flow, dir, flow_rule);
|
||||
if (flow_offload_decap_tunnel(flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_encap_tunnel(flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
|
||||
if (flow_offload_eth_src(net, flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_eth_dst(net, flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
|
||||
if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
||||
flow_offload_ipv6_snat(net, flow, dir, flow_rule);
|
||||
flow_offload_port_snat(net, flow, dir, flow_rule);
|
||||
if (flow_offload_ipv6_snat(net, flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_port_snat(net, flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
}
|
||||
if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
|
||||
flow_offload_ipv6_dnat(net, flow, dir, flow_rule);
|
||||
flow_offload_port_dnat(net, flow, dir, flow_rule);
|
||||
if (flow_offload_ipv6_dnat(net, flow, dir, flow_rule) < 0 ||
|
||||
flow_offload_port_dnat(net, flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
flow_offload_redirect(flow, dir, flow_rule);
|
||||
if (flow_offload_redirect(flow, dir, flow_rule) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_flow_rule_route_ipv6);
|
||||
|
||||
#define NF_FLOW_RULE_ACTION_MAX 16
|
||||
|
||||
static struct nf_flow_rule *
|
||||
nf_flow_offload_rule_alloc(struct net *net,
|
||||
const struct flow_offload_work *offload,
|
||||
|
||||
@ -135,7 +135,9 @@ static int nft_immediate_offload_verdict(struct nft_offload_ctx *ctx,
|
||||
struct flow_action_entry *entry;
|
||||
const struct nft_data *data;
|
||||
|
||||
entry = &flow->rule->action.entries[ctx->num_actions++];
|
||||
entry = nft_flow_action_entry_next(ctx, flow);
|
||||
if (!entry)
|
||||
return -E2BIG;
|
||||
|
||||
data = &priv->data;
|
||||
switch (data->verdict.code) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user