Пример #1
0
static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
			   const struct ovs_conntrack_info *info,
			   struct sk_buff *skb)
{
	/* If we are recirculating packets to match on conntrack fields and
	 * committing with a separate conntrack action,  then we don't need to
	 * actually run the packet through conntrack twice unless it's for a
	 * different zone.
	 */
	if (!skb_nfct_cached(net, skb, info)) {
		struct nf_conn *tmpl = info->ct;

		/* Associate skb with specified zone. */
		if (tmpl) {
			if (skb->nfct)
				nf_conntrack_put(skb->nfct);
			nf_conntrack_get(&tmpl->ct_general);
			skb->nfct = &tmpl->ct_general;
			skb->nfctinfo = IP_CT_NEW;
		}

		if (nf_conntrack_in(net, info->family, NF_INET_FORWARD,
				    skb) != NF_ACCEPT)
			return -ENOENT;

		if (ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
			WARN_ONCE(1, "helper rejected packet");
			return -EINVAL;
		}
	}

	ovs_ct_update_key(skb, info, key, true);

	return 0;
}
Пример #2
0
/* Lookup connection and confirm if unconfirmed. */
static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
                         const struct ovs_conntrack_info *info,
                         struct sk_buff *skb)
{
    u8 state;
    int err;

    state = key->ct.state;
    if (key->ct.zone == info->zone.id &&
            ((state & OVS_CS_F_TRACKED) && !(state & OVS_CS_F_NEW))) {
        /* Previous lookup has shown that this connection is already
         * tracked and committed. Skip committing.
         */
        return 0;
    }

    err = __ovs_ct_lookup(net, key, info, skb);
    if (err)
        return err;
    if (nf_conntrack_confirm(skb) != NF_ACCEPT)
        return -EINVAL;

    ovs_ct_update_key(skb, key, true);

    return 0;
}
Пример #3
0
/* Lookup connection and read fields into key. */
static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                         const struct ovs_conntrack_info *info,
                         struct sk_buff *skb)
{
    struct nf_conntrack_expect *exp;

    exp = ovs_ct_expect_find(net, &info->zone, info->family, skb);
    if (exp) {
        u8 state;

        state = OVS_CS_F_TRACKED | OVS_CS_F_NEW | OVS_CS_F_RELATED;
        __ovs_ct_update_key(key, state, &info->zone, exp->master);
    } else {
        int err;

        err = __ovs_ct_lookup(net, key, info, skb);
        if (err)
            return err;

        ovs_ct_update_key(skb, key, true);
    }

    return 0;
}
Пример #4
0
void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
{
	ovs_ct_update_key(skb, NULL, key, false);
}