Skip to content

Commit

Permalink
Merge "Avoiding the Ecmp trap mesages to Agent"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Aug 27, 2016
2 parents 838d1d6 + 6a8ab5d commit 16e04bf
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 59 deletions.
66 changes: 51 additions & 15 deletions dp-core/vr_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,21 +769,59 @@ vr_flow_get_qos(struct vrouter *router, struct vr_packet *pkt,
return -1;
}

static int
vr_rflow_update_ecmp_index(struct vrouter *router, struct vr_flow_entry *fe,
unsigned int new_ecmp_index, struct vr_forwarding_md *fmd)
{
struct vr_flow_entry *rfe;

if (new_ecmp_index == -1)
return -1;

rfe = vr_flow_get_entry(router, fe->fe_rflow);
if ((!rfe) || (rfe->fe_flags & VR_FLOW_FLAG_DELETE_MARKED))
return -1;

rfe->fe_ecmp_nh_index = new_ecmp_index;

fmd->fmd_ecmp_src_nh_index = new_ecmp_index;

return 0;
}


int
vr_flow_update_ecmp_index(struct vrouter *router, struct vr_flow_entry *fe,
unsigned int new_ecmp_index, struct vr_forwarding_md *fmd)
{

if (new_ecmp_index == -1)
return -1;

if ((!fe) || (fe->fe_flags & VR_FLOW_FLAG_DELETE_MARKED))
return -1;

/* If RPF verification is manipulating this flow, let it succeed */
(void)__sync_bool_compare_and_swap(&fe->fe_ecmp_nh_index,
fmd->fmd_ecmp_nh_index, new_ecmp_index);

fmd->fmd_ecmp_nh_index = fe->fe_ecmp_nh_index;

return 0;
}

static flow_result_t
vr_flow_action(struct vrouter *router, struct vr_flow_entry *fe,
unsigned int index, struct vr_packet *pkt,
struct vr_forwarding_md *fmd)
{
int valid_src;
int valid_src, modified_index = -1;
unsigned int ip_inc_diff_cksum = 0;
struct vr_ip *ip;

flow_result_t result;

struct vr_forwarding_md mirror_fmd;
struct vr_nexthop *src_nh;
struct vr_packet *pkt_clone;

fmd->fmd_dvrf = fe->fe_vrf;
/*
Expand All @@ -797,23 +835,18 @@ vr_flow_action(struct vrouter *router, struct vr_flow_entry *fe,
}

if (src_nh->nh_validate_src) {
valid_src = src_nh->nh_validate_src(pkt, src_nh, fmd, NULL);
valid_src = src_nh->nh_validate_src(pkt, src_nh, fmd, &modified_index);
if (valid_src == NH_SOURCE_INVALID) {
vr_pfree(pkt, VP_DROP_INVALID_SOURCE);
return FLOW_CONSUMED;
}

if (valid_src == NH_SOURCE_MISMATCH) {
pkt_clone = vr_pclone(pkt);
if (pkt_clone) {
vr_preset(pkt_clone);
if (vr_pcow(pkt_clone, sizeof(struct vr_eth) +
sizeof(struct agent_hdr))) {
vr_pfree(pkt_clone, VP_DROP_PCOW_FAIL);
} else {
vr_trap(pkt_clone, fmd->fmd_dvrf,
AGENT_TRAP_ECMP_RESOLVE, &fmd->fmd_flow_index);
}
valid_src = vr_rflow_update_ecmp_index(router, fe,
modified_index, fmd);
if (valid_src == -1) {
vr_pfree(pkt, VP_DROP_INVALID_SOURCE);
return FLOW_CONSUMED;
}
}
}
Expand Down Expand Up @@ -1956,7 +1989,10 @@ vr_flow_set(struct vrouter *router, vr_flow_req *req)

vr_flow_update_link_local_port(router, req, fe);

fe->fe_ecmp_nh_index = req->fr_ecmp_nh_index;
if (fe->fe_ecmp_nh_index == -1)
(void)__sync_bool_compare_and_swap(&fe->fe_ecmp_nh_index, -1,
req->fr_ecmp_nh_index);

fe->fe_src_nh_index = req->fr_src_nh_index;
fe->fe_qos_id = req->fr_qos_id;

Expand Down
106 changes: 63 additions & 43 deletions dp-core/vr_nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,24 +563,25 @@ nh_composite_ecmp_validate_src(struct vr_packet *pkt, struct vr_nexthop *nh,
struct vr_forwarding_md *fmd, void *ret_data)
{
int i;
struct vr_nexthop *cnh;
struct vr_nexthop *cnh = NULL;

/* the first few checks are straight forward */
if (!fmd || (uint8_t)fmd->fmd_ecmp_src_nh_index >= nh->nh_component_cnt)
if (!fmd)
return NH_SOURCE_INVALID;

cnh = nh->nh_component_nh[fmd->fmd_ecmp_src_nh_index].cnh;
if (cnh && !cnh->nh_validate_src)
return NH_SOURCE_INVALID;
if ((fmd->fmd_ecmp_src_nh_index >= 0) &&
(fmd->fmd_ecmp_src_nh_index < nh->nh_component_cnt)) {
cnh = nh->nh_component_nh[fmd->fmd_ecmp_src_nh_index].cnh;
}

/*
* when the 'supposed' source goes down, cnh is null, in which
* case validate the source against other present nexthops. follow
* the same logic if the component validate source returns invalid
* source, which could mean that source has moved
*/
if (!cnh || (NH_SOURCE_INVALID ==
cnh->nh_validate_src(pkt, cnh, fmd, NULL))) {
if (!cnh || (!cnh->nh_validate_src) ||
(NH_SOURCE_INVALID == cnh->nh_validate_src(pkt, cnh, fmd, NULL))) {
for (i = 0; i < nh->nh_component_cnt; i++) {
if (i == fmd->fmd_ecmp_src_nh_index)
continue;
Expand All @@ -596,8 +597,12 @@ nh_composite_ecmp_validate_src(struct vr_packet *pkt, struct vr_nexthop *nh,
* return mismatch
*/
if ((NH_SOURCE_VALID ==
cnh->nh_validate_src(pkt, cnh, fmd, NULL)))
cnh->nh_validate_src(pkt, cnh, fmd, NULL))) {
if (ret_data) {
*(unsigned int *)ret_data = i;
}
return NH_SOURCE_MISMATCH;
}
}

/* if everything else fails, source is indeed invalid */
Expand All @@ -608,36 +613,47 @@ nh_composite_ecmp_validate_src(struct vr_packet *pkt, struct vr_nexthop *nh,
return NH_SOURCE_VALID;
}

static struct vr_nexthop *
static int
nh_composite_ecmp_select_nh(struct vr_packet *pkt, struct vr_nexthop *nh,
struct vr_forwarding_md *fmd)
{
int ret, ecmp_index;
int ret = -1, ecmp_index;
unsigned int hash, hash_ecmp, count;

struct vr_flow flow;
struct vr_flow flow, *flowp = &flow;
struct vr_flow_entry *fe = NULL;
struct vr_ip6 *ip6;
struct vr_nexthop *cnh = NULL;
struct vr_component_nh *cnhp = nh->nh_component_nh;

if (!(count = nh->nh_component_cnt))
return NULL;
if (!nh || !fmd || (!nh->nh_component_cnt))
return ret;

if (pkt->vp_type == VP_TYPE_IP) {
ret = vr_inet_get_flow_key(nh->nh_router, pkt, fmd, &flow);
if (ret < 0)
return NULL;
} else if (pkt->vp_type == VP_TYPE_IP6) {
ip6 = (struct vr_ip6 *)pkt_network_header(pkt);
ret = vr_inet6_form_flow(nh->nh_router, fmd->fmd_dvrf, pkt,
fmd->fmd_vlan, ip6, &flow);
if (ret < 0)
return NULL;
} else {
return NULL;
count = nh->nh_component_cnt;

if (fmd->fmd_flow_index >= 0) {
fe = vr_flow_get_entry(nh->nh_router, fmd->fmd_flow_index);
if (fe)
flowp = &fe->fe_key;
}

hash = hash_ecmp = vr_hash(&flow, flow.flow_key_len, 0);
if (!fe) {
if (pkt->vp_type == VP_TYPE_IP) {
ret = vr_inet_get_flow_key(nh->nh_router, pkt, fmd, flowp);
if (ret < 0)
return ret;
} else if (pkt->vp_type == VP_TYPE_IP6) {
ip6 = (struct vr_ip6 *)pkt_network_header(pkt);
ret = vr_inet6_form_flow(nh->nh_router, fmd->fmd_dvrf, pkt,
fmd->fmd_vlan, ip6, flowp);
if (ret < 0)
return ret;
} else {
return ret;
}
}

hash = hash_ecmp = vr_hash(flowp, flowp->flow_key_len, 0);
hash %= count;
ecmp_index = cnhp[hash].cnh_ecmp_index;
cnh = cnhp[hash].cnh;
Expand All @@ -646,45 +662,49 @@ nh_composite_ecmp_select_nh(struct vr_packet *pkt, struct vr_nexthop *nh,
cnhp = nh->nh_component_ecmp;
hash_ecmp %= nh->nh_component_ecmp_cnt;
ecmp_index = cnhp[hash_ecmp].cnh_ecmp_index;
cnh = cnhp[hash_ecmp].cnh;
if (!(cnh = cnhp[hash_ecmp].cnh))
return -1;
}
}

if (cnh)
fmd->fmd_ecmp_nh_index = ecmp_index;
if (fe)
return vr_flow_update_ecmp_index(nh->nh_router, fe, ecmp_index, fmd);

return cnh;
fmd->fmd_ecmp_nh_index = ecmp_index;

return 0;
}

static int
nh_composite_ecmp(struct vr_packet *pkt, struct vr_nexthop *nh,
struct vr_forwarding_md *fmd)
{
int ret = 0;
int ret = 0, drop_reason = VP_DROP_INVALID_NH;
struct vr_nexthop *member_nh = NULL;
struct vr_vrf_stats *stats;

stats = vr_inet_vrf_stats(fmd->fmd_dvrf, pkt->vp_cpu);
if (stats)
stats->vrf_ecmp_composites++;

if (!fmd || fmd->fmd_ecmp_nh_index >= (short)nh->nh_component_cnt)
if (!fmd) {
drop_reason = VP_DROP_NO_FMD;
goto drop;
}

if (fmd->fmd_ecmp_nh_index >= 0) {
if ((fmd->fmd_ecmp_nh_index >= 0) &&
(fmd->fmd_ecmp_nh_index < nh->nh_component_cnt)) {
member_nh = nh->nh_component_nh[fmd->fmd_ecmp_nh_index].cnh;
} else if (fmd->fmd_flow_index < 0) {
member_nh = nh_composite_ecmp_select_nh(pkt, nh, fmd);
}

if (!member_nh) {
if (fmd->fmd_flow_index < 0) {
vr_pfree(pkt, VP_DROP_INVALID_NH);
return 0;
} else {
vr_trap(pkt, fmd->fmd_dvrf, AGENT_TRAP_ECMP_RESOLVE, &fmd->fmd_flow_index);
return 0;
}
ret = nh_composite_ecmp_select_nh(pkt, nh, fmd);
if (ret)
goto drop;

member_nh = nh->nh_component_nh[fmd->fmd_ecmp_nh_index].cnh;
if (!member_nh)
goto drop;
}

vr_forwarding_md_set_label(fmd,
Expand All @@ -693,7 +713,7 @@ nh_composite_ecmp(struct vr_packet *pkt, struct vr_nexthop *nh,
return nh_output(pkt, member_nh, fmd);

drop:
vr_pfree(pkt, VP_DROP_NO_FMD);
vr_pfree(pkt, drop_reason);
return ret;
}

Expand Down
3 changes: 2 additions & 1 deletion include/vr_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ extern int16_t vr_flow_get_qos(struct vrouter *, struct vr_packet *,
struct vr_forwarding_md *);
unsigned int vr_flow_table_used_oflow_entries(struct vrouter *);
unsigned int vr_flow_table_used_total_entries(struct vrouter *);

int vr_flow_update_ecmp_index(struct vrouter *, struct vr_flow_entry *,
unsigned int, struct vr_forwarding_md *);

#endif /* __VR_FLOW_H__ */

0 comments on commit 16e04bf

Please sign in to comment.