Skip to content

Commit

Permalink
Fix for flow creation for IPv6
Browse files Browse the repository at this point in the history
When VN configured with fat flow and icmp6 error is
generated, flows are not created on the destination VN.

Change-Id: I203d80cfdc2625f463c19359a40a9f166d47ba20
Partial-Bug: #1766559
  • Loading branch information
esnagendra committed Jul 30, 2018
1 parent 32589f0 commit ff467f0
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 40 deletions.
83 changes: 45 additions & 38 deletions dp-core/vr_proto_ip6.c
Expand Up @@ -189,7 +189,8 @@ vr_inet6_fill_rflow_from_req(struct vr_flow *flow_p, vr_flow_req *req)

void
vr_inet6_fill_flow(struct vr_flow *flow_p, unsigned short nh_id,
unsigned char *ip, uint8_t proto, uint16_t sport, uint16_t dport,
unsigned char *sip, unsigned char *dip,
uint8_t proto, uint16_t sport, uint16_t dport,
uint8_t valid_fkey_params)
{
memset(flow_p, 0, VR_FLOW_IPV6_HASH_SIZE);
Expand All @@ -199,30 +200,10 @@ vr_inet6_fill_flow(struct vr_flow *flow_p, unsigned short nh_id,
AF_INET6, valid_fkey_params);

if (valid_fkey_params & VR_FLOW_KEY_SRC_IP)
memcpy(flow_p->flow_ip, ip, VR_IP6_ADDRESS_LEN);
memcpy(flow_p->flow_ip, sip, VR_IP6_ADDRESS_LEN);

if (valid_fkey_params & VR_FLOW_KEY_DST_IP)
memcpy(flow_p->flow_ip + VR_IP6_ADDRESS_LEN,
ip + VR_IP6_ADDRESS_LEN, VR_IP6_ADDRESS_LEN);

return;
}

static void
vr_inet6_flow_swap(struct vr_flow *key_p)
{
unsigned short port;
uint8_t ip6_addr[VR_IP6_ADDRESS_LEN];

if (key_p->flow6_proto != VR_IP_PROTO_ICMP6) {
port = key_p->flow6_sport;
key_p->flow6_sport = key_p->flow6_dport;
key_p->flow6_dport = port;
}

memcpy(ip6_addr, key_p->flow6_sip, VR_IP6_ADDRESS_LEN);
memcpy(key_p->flow6_sip, key_p->flow6_dip, VR_IP6_ADDRESS_LEN);
memcpy(key_p->flow6_dip, ip6_addr, VR_IP6_ADDRESS_LEN);
memcpy(flow_p->flow_ip + VR_IP6_ADDRESS_LEN, dip, VR_IP6_ADDRESS_LEN);

return;
}
Expand All @@ -246,11 +227,13 @@ vr_inet6_flow_is_fat_flow(struct vrouter *router, struct vr_packet *pkt,
static int
vr_inet6_proto_flow(struct vrouter *router, unsigned short vrf,
struct vr_packet *pkt, uint16_t vlan, struct vr_ip6 *ip6,
struct vr_flow *flow_p, uint8_t valid_fkey_params, bool frag_calc)
struct vr_flow *flow_p, uint8_t valid_fkey_params,
bool frag_calc, bool forward)
{
int i, ret = 0;
uint8_t ip6_nxt;
unsigned short *t_hdr, sport, dport, nh_id,
unsigned char *ip6_src, *ip6_dst, *ip6_addr;
unsigned short *t_hdr, sport, dport, port, nh_id,
fat_flow_mask = VR_FAT_FLOW_NO_MASK;
struct vr_ip6_frag *v6_frag;
struct vr_icmp *icmph;
Expand All @@ -270,11 +253,9 @@ vr_inet6_proto_flow(struct vrouter *router, unsigned short vrf,
if ((unsigned char *)ip6 == pkt_network_header(pkt)) {
ret = vr_inet6_form_flow(router, vrf, pkt, vlan,
(struct vr_ip6 *)(icmph + 1), flow_p,
valid_fkey_params, frag_calc);
if (ret)
return ret;
valid_fkey_params, frag_calc, false);

vr_inet6_flow_swap(flow_p);
return ret;
} else {
return -1;
}
Expand Down Expand Up @@ -302,6 +283,18 @@ vr_inet6_proto_flow(struct vrouter *router, unsigned short vrf,
dport = 0;
}

ip6_src = (unsigned char *)&ip6->ip6_src;
ip6_dst = (unsigned char *)&ip6->ip6_dst;
if (!forward) {
port = sport;
sport = dport;
dport = port;

ip6_addr = ip6_src;
ip6_src = ip6_dst;
ip6_dst = ip6_addr;
}

fat_flow_mask = vr_flow_fat_flow_lookup(router, pkt, ip6_nxt,
sport, dport);
for (i = 1; i < VR_FAT_FLOW_MAX_MASK; i = i << 1) {
Expand Down Expand Up @@ -330,7 +323,7 @@ vr_inet6_proto_flow(struct vrouter *router, unsigned short vrf,
valid_fkey_params &= VR_FLOW_KEY_ALL;

nh_id = vr_inet_flow_nexthop(pkt, vlan);
vr_inet6_fill_flow(flow_p, nh_id, (unsigned char *)&ip6->ip6_src,
vr_inet6_fill_flow(flow_p, nh_id, ip6_src, ip6_dst,
ip6_nxt, sport, dport, valid_fkey_params);

return 0;
Expand All @@ -339,9 +332,11 @@ vr_inet6_proto_flow(struct vrouter *router, unsigned short vrf,
static int
vr_inet6_fragment_flow(struct vrouter *router, unsigned short vrf,
struct vr_packet *pkt, uint16_t vlan, struct vr_ip6 *ip6,
struct vr_flow *flow_p, uint8_t valid_fkey_params, bool frag_calc)
struct vr_flow *flow_p, uint8_t valid_fkey_params,
bool frag_calc, bool forward)
{
uint16_t sport, dport;
uint16_t sport, dport, port;
unsigned char *ip6_src, *ip6_dst, *ip6_addr;
unsigned short nh_id;
struct vr_fragment *frag;
struct vr_ip6_frag *v6_frag;
Expand All @@ -368,9 +363,20 @@ vr_inet6_fragment_flow(struct vrouter *router, unsigned short vrf,
}
}

ip6_src = (unsigned char *)&ip6->ip6_src;
ip6_dst = (unsigned char *)&ip6->ip6_dst;
if (!forward) {
port = sport;
sport = dport;
dport = port;

ip6_addr = ip6_src;
ip6_src = ip6_dst;
ip6_dst = ip6_addr;
}

nh_id = vr_inet_flow_nexthop(pkt, vlan);
vr_inet6_fill_flow(flow_p, nh_id, (unsigned char *)&ip6->ip6_src,
vr_inet6_fill_flow(flow_p, nh_id, ip6_src, ip6_dst,
v6_frag->ip6_frag_nxt, sport, dport, valid_fkey_params);

return 0;
Expand All @@ -380,16 +386,17 @@ vr_inet6_fragment_flow(struct vrouter *router, unsigned short vrf,
int
vr_inet6_form_flow(struct vrouter *router, unsigned short vrf,
struct vr_packet *pkt, uint16_t vlan, struct vr_ip6 *ip6,
struct vr_flow *flow_p, uint8_t valid_fkey_params, bool frag_calc)
struct vr_flow *flow_p, uint8_t valid_fkey_params,
bool frag_calc, bool forward)
{
int ret = 0;

if (vr_ip6_transport_header_valid(ip6)) {
ret = vr_inet6_proto_flow(router, vrf, pkt, vlan, ip6, flow_p,
valid_fkey_params, frag_calc);
valid_fkey_params, frag_calc, forward);
} else {
ret = vr_inet6_fragment_flow(router, vrf, pkt, vlan, ip6,
flow_p, valid_fkey_params, frag_calc);
flow_p, valid_fkey_params, frag_calc, forward);
}

return ret;
Expand All @@ -406,7 +413,7 @@ vr_inet6_get_flow_key(struct vrouter *router, unsigned short vrf,

ip6 = (struct vr_ip6 *)pkt_network_header(pkt);
ret = vr_inet6_form_flow(router, vrf, pkt, vlan, ip6, flow_p,
valid_fkey_params, false);
valid_fkey_params, false, true);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -448,7 +455,7 @@ vr_inet6_flow_lookup(struct vrouter *router, struct vr_packet *pkt,
return FLOW_FORWARD;

ret = vr_inet6_form_flow(router, fmd->fmd_dvrf, pkt, fmd->fmd_vlan,
ip6, flow_p, VR_FLOW_KEY_ALL, true);
ip6, flow_p, VR_FLOW_KEY_ALL, true, true);
if (ret < 0) {
if (!vr_ip6_transport_header_valid(ip6) && vr_enqueue_to_assembler) {
vr_enqueue_to_assembler(router, pkt, fmd);
Expand Down
4 changes: 2 additions & 2 deletions include/vr_flow.h
Expand Up @@ -469,7 +469,7 @@ flow_result_t vr_inet_flow_lookup(struct vrouter *, struct vr_packet *,
flow_result_t vr_inet6_flow_lookup(struct vrouter *, struct vr_packet *,
struct vr_forwarding_md *);
int vr_inet6_form_flow(struct vrouter *, unsigned short, struct vr_packet *,
uint16_t, struct vr_ip6 *, struct vr_flow *, uint8_t, bool);
uint16_t, struct vr_ip6 *, struct vr_flow *, uint8_t, bool, bool);
int vr_inet6_get_flow_key(struct vrouter *, unsigned short, struct vr_packet *,
uint16_t, struct vr_flow *, uint8_t);

Expand All @@ -479,7 +479,7 @@ extern flow_result_t vr_inet_flow_nat(struct vr_flow_entry *,
extern void vr_inet_fill_flow(struct vr_flow *, unsigned short,
uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint8_t);
extern void vr_inet6_fill_flow(struct vr_flow *, unsigned short,
unsigned char *, uint8_t, uint16_t, uint16_t, uint8_t);
unsigned char *, unsigned char *, uint8_t, uint16_t, uint16_t, uint8_t);
extern void vr_inet6_fill_flow_from_req(struct vr_flow *,
struct _vr_flow_req *);
extern void vr_inet6_fill_rflow_from_req(struct vr_flow *,
Expand Down

0 comments on commit ff467f0

Please sign in to comment.