staticbool tcf_mirred_act_wants_ingress(int action)
{ switch (action) { case TCA_EGRESS_REDIR: case TCA_EGRESS_MIRROR: returnfalse; case TCA_INGRESS_REDIR: case TCA_INGRESS_MIRROR: returntrue; default:
BUG();
}
}
staticbool tcf_mirred_can_reinsert(int action)
{ switch (action) { case TC_ACT_SHOT: case TC_ACT_STOLEN: case TC_ACT_QUEUED: case TC_ACT_TRAP: returntrue;
} returnfalse;
}
if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed"); return -EINVAL;
}
ret = nla_parse_nested_deprecated(tb, TCA_MIRRED_MAX, nla,
mirred_policy, extack); if (ret < 0) return ret; if (!tb[TCA_MIRRED_PARMS]) {
NL_SET_ERR_MSG_MOD(extack, "Missing required mirred parameters"); return -EINVAL;
}
parm = nla_data(tb[TCA_MIRRED_PARMS]);
index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind); if (err < 0) return err;
exists = err; if (exists && bind) return ACT_P_BOUND;
if (tb[TCA_MIRRED_BLOCKID] && parm->ifindex) {
NL_SET_ERR_MSG_MOD(extack, "Cannot specify Block ID and dev simultaneously"); if (exists)
tcf_idr_release(*a, bind); else
tcf_idr_cleanup(tn, index);
return -EINVAL;
}
switch (parm->eaction) { case TCA_EGRESS_MIRROR: case TCA_EGRESS_REDIR: case TCA_INGRESS_REDIR: case TCA_INGRESS_MIRROR: break; default: if (exists)
tcf_idr_release(*a, bind); else
tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option"); return -EINVAL;
}
if (!exists) { if (!parm->ifindex && !tb[TCA_MIRRED_BLOCKID]) {
tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Must specify device or block"); return -EINVAL;
}
ret = tcf_idr_create_from_flags(tn, index, est, a,
&act_mirred_ops, bind, flags); if (ret) {
tcf_idr_cleanup(tn, index); return ret;
}
ret = ACT_P_CREATED;
} elseif (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); return -EEXIST;
}
m = to_mirred(*a); if (ret == ACT_P_CREATED)
INIT_LIST_HEAD(&m->tcfm_list);
staticint tcf_mirred_to_dev(struct sk_buff *skb, struct tcf_mirred *m, struct net_device *dev, constbool m_mac_header_xmit, int m_eaction, int retval)
{ struct sk_buff *skb_to_send = skb; bool want_ingress; bool is_redirect; bool expects_nh; bool at_ingress; bool dont_clone; int mac_len; bool at_nh; int err;
is_redirect = tcf_mirred_is_act_redirect(m_eaction); if (unlikely(!(dev->flags & IFF_UP)) || !netif_carrier_ok(dev)) {
net_notice_ratelimited("tc mirred to Houston: device %s is down\n",
dev->name); goto err_cant_do;
}
/* we could easily avoid the clone only if called by ingress and clsact; *sincewecan'teasilydetecttheclsactcaller,skipcloneonlyfor *ingress-thatcoverstheTCS/Wdatapath.
*/
at_ingress = skb_at_tc_ingress(skb);
dont_clone = skb_at_tc_ingress(skb) && is_redirect &&
tcf_mirred_can_reinsert(retval); if (!dont_clone) {
skb_to_send = skb_clone(skb, GFP_ATOMIC); if (!skb_to_send) goto err_cant_do;
}
/* All mirred/redirected skbs should clear previous ct info */
nf_reset_ct(skb_to_send); if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */
skb_dst_drop(skb_to_send);
expects_nh = want_ingress || !m_mac_header_xmit;
at_nh = skb->data == skb_network_header(skb); if (at_nh != expects_nh) {
mac_len = at_ingress ? skb->mac_len :
skb_network_offset(skb); if (expects_nh) { /* target device/action expect data at nh */
skb_pull_rcsum(skb_to_send, mac_len);
} else { /* target device/action expect data at mac */
skb_push_rcsum(skb_to_send, mac_len);
}
}
/* we are already under rcu protection, so can call block lookup *directly.
*/
block = tcf_block_lookup(dev_net(skb->dev), blockid); if (!block || xa_empty(&block->ports)) {
tcf_action_inc_overlimit_qstats(&m->common); return retval;
}
if (is_redirect) return tcf_blockcast_redir(skb, m, block, m_eaction,
exception_ifindex, retval);
/* If it's not redirect, it is mirror */ return tcf_blockcast_mirror(skb, m, block, m_eaction, exception_ifindex,
retval);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.11Bemerkung:
(vorverarbeitet am 2026-10-11)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.