Skip to content

Commit

Permalink
Limit the number of component nexthops that are dumped
Browse files Browse the repository at this point in the history
If the number of component nexthops are huge, with the current logic
of allocating memory for the encoding buffer in vrouter, a dump
operation can fail because of insufficient memory. For such a huge list
it doesn't make sense to dump all the component nexthops in a DUMP
operation. We will limit the dump to a smaller number and ask users to
do a GET operation of the parent nexthop to get the complete list.

Closes BUG: 1466607

Change-Id: Ia774eba66364a8aa761d8544fee3911a37e39a79
  • Loading branch information
anandhk-juniper committed Sep 14, 2015
1 parent 675fa2e commit 593f6a9
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 22 deletions.
43 changes: 32 additions & 11 deletions dp-core/vr_nexthop.c
Expand Up @@ -2346,12 +2346,28 @@ vr_nexthop_add(vr_nexthop_req *req)
return ret;
}

unsigned int
vr_nexthop_req_get_size(void *req_p)
{
vr_nexthop_req *req = (vr_nexthop_req *)req_p;

if (req->nhr_type == NH_COMPOSITE)
return (4 * sizeof(*req) + (req->nhr_nh_list_size * 4));

return 4 * sizeof(*req);
}

/* we expect the caller to bzero req, before sending it here */
static int
vr_nexthop_make_req(vr_nexthop_req *req, struct vr_nexthop *nh)
{
unsigned char *encap = NULL;
unsigned int i;
unsigned char *encap = NULL;

bool dump = false;

if (req->h_op == SANDESH_OP_DUMP)
dump = true;

req->nhr_type = nh->nh_type;
req->nhr_family = nh->nh_family;
Expand Down Expand Up @@ -2384,15 +2400,18 @@ vr_nexthop_make_req(vr_nexthop_req *req, struct vr_nexthop *nh)
break;

case NH_COMPOSITE:
req->nhr_nh_list_size = nh->nh_component_cnt;
req->nhr_nh_list_size = req->nhr_nh_count = nh->nh_component_cnt;
if (dump && (req->nhr_nh_list_size > VR_NEXTHOP_COMPONENT_DUMP_LIMIT))
req->nhr_nh_list_size = VR_NEXTHOP_COMPONENT_DUMP_LIMIT;

if (nh->nh_component_cnt) {
req->nhr_nh_list =
vr_zalloc(req->nhr_nh_list_size * sizeof(unsigned int),
VR_NEXTHOP_REQ_LIST_OBJECT);
if (!req->nhr_nh_list)
return -ENOMEM;

req->nhr_label_list_size = nh->nh_component_cnt;
req->nhr_label_list_size = req->nhr_nh_list_size;
req->nhr_label_list =
vr_zalloc(req->nhr_nh_list_size * sizeof(unsigned int),
VR_NEXTHOP_REQ_LIST_OBJECT);
Expand Down Expand Up @@ -2519,6 +2538,7 @@ vr_nexthop_get(vr_nexthop_req *req)
nh = __vrouter_get_nexthop(router, req->nhr_id);
if (nh) {
resp = vr_nexthop_req_get();
resp->h_op = SANDESH_OP_GET;
if (resp)
ret = vr_nexthop_make_req(resp, nh);
else
Expand Down Expand Up @@ -2562,15 +2582,16 @@ vr_nexthop_dump(vr_nexthop_req *r)
if (!resp && (ret = -ENOMEM))
goto generate_response;

ret = vr_nexthop_make_req(resp, nh);
if (ret || ((ret = vr_message_dump_object(dumper,
VR_NEXTHOP_OBJECT_ID, resp)) <= 0)) {
vr_nexthop_req_destroy(resp);
if (ret <= 0)
break;
}
resp->h_op = SANDESH_OP_DUMP;
ret = vr_nexthop_make_req(resp, nh);
if (ret || ((ret = vr_message_dump_object(dumper,
VR_NEXTHOP_OBJECT_ID, resp)) <= 0)) {
vr_nexthop_req_destroy(resp);
if (ret <= 0)
break;
}

vr_nexthop_req_destroy(resp);
vr_nexthop_req_destroy(resp);
}
}

Expand Down
4 changes: 4 additions & 0 deletions dp-core/vr_sandesh.c
Expand Up @@ -20,6 +20,7 @@ struct sandesh_object_md sandesh_md[] = {
},
[VR_NEXTHOP_OBJECT_ID] = {
.obj_len = 4 * sizeof(vr_nexthop_req),
.obj_get_size = vr_nexthop_req_get_size,
.obj_type_string = "vr_nexthop_req",
},
[VR_ROUTE_OBJECT_ID] = {
Expand Down Expand Up @@ -79,6 +80,9 @@ sandesh_proto_buf_len(unsigned int object_type, void *object)
if (!object && object_type != VR_RESPONSE_OBJECT_ID)
return 0;

if (sandesh_md[object_type].obj_get_size)
return sandesh_md[object_type].obj_get_size(object);

return sandesh_md[object_type].obj_len;
}

Expand Down
4 changes: 4 additions & 0 deletions include/vr_nexthop.h
Expand Up @@ -16,6 +16,9 @@ extern "C" {
*/
#define VR_DEF_NEXTHOPS 65536
#define NH_TABLE_ENTRIES VR_DEF_NEXTHOPS

#define VR_NEXTHOP_COMPONENT_DUMP_LIMIT 16

#define NH_DISCARD_ID 0

enum nexthop_type {
Expand Down Expand Up @@ -157,6 +160,7 @@ extern int vr_nexthop_add(vr_nexthop_req *);
extern int vr_nexthop_get(vr_nexthop_req *);
extern int vr_nexthop_dump(vr_nexthop_req *);
extern bool vr_gateway_nexthop(struct vr_nexthop *);
extern unsigned int vr_nexthop_req_get_size(void *);

extern struct vr_nexthop *vr_discard_nh;
#ifdef __cplusplus
Expand Down
1 change: 1 addition & 0 deletions include/vr_sandesh.h
Expand Up @@ -11,6 +11,7 @@
struct sandesh_object_md {
unsigned int obj_len;
char *obj_type_string;
unsigned int (*obj_get_size)(void *);
};

void *sandesh_alloc(unsigned int);
Expand Down
1 change: 1 addition & 0 deletions sandesh/vr.sandesh
Expand Up @@ -45,6 +45,7 @@ buffer sandesh vr_nexthop_req {
18: list<i32> nhr_nh_list;
19: i32 nhr_label;
20: list<i32> nhr_label_list;
21: i16 nhr_nh_count;
}

buffer sandesh vr_interface_req {
Expand Down
36 changes: 25 additions & 11 deletions utils/nh.c
Expand Up @@ -35,7 +35,7 @@ static uint32_t nh_id, if_id, vrf_id, flags;
static int nh_set, command, type, dump_marker = -1;

static bool dump_pending = false;
static int comp_nh[10], lbl[10];
static int comp_nh[32], lbl[32];
static int comp_nh_ind = 0, lbl_ind = 0;

static struct in_addr sip, dip;
Expand Down Expand Up @@ -182,7 +182,7 @@ nh_print_newline_header(void)
void
vr_nexthop_req_process(void *s_req)
{
unsigned int i;
unsigned int i, printed = 0;
struct in_addr a;
char flags_mem[500];
char fam[100];
Expand All @@ -198,21 +198,25 @@ vr_nexthop_req_process(void *s_req)
else
strcpy(fam, "N/A");

printf("Id:%-9d Type:%-8s Fmly:%8s Flags:%s Rid:%d Ref_cnt:%d Vrf:%d",
printf("Id:%-9d Type:%-13s Fmly:%8s Rid:%d Ref_cnt:%-10d Vrf:%d",
req->nhr_id, nh_type(req->nhr_type), fam,
nh_flags(req->nhr_flags, req->nhr_type, flags_mem),
req->nhr_rid, req->nhr_ref_cnt, req->nhr_vrf);
nh_print_newline_header();
printf("Flags:%s",
nh_flags(req->nhr_flags, req->nhr_type, flags_mem));

if (req->nhr_type == NH_RCV) {
nh_print_newline_header();
printf("Oif:%d\n", req->nhr_encap_oif_id);
} else if (req->nhr_type == NH_ENCAP) {
nh_print_newline_header();
printf("EncapFmly:%04x Oif:%d Len:%d Data:", req->nhr_encap_family, req->nhr_encap_oif_id, req->nhr_encap_size);
printf("EncapFmly:%04x Oif:%d Len:%d", ' ',
req->nhr_encap_family, req->nhr_encap_oif_id, req->nhr_encap_size);
nh_print_newline_header();
printf("Encap Data: ", ' ');
for (i = 0; i< req->nhr_encap_size; i++) {
printf("%02x ", (unsigned char)req->nhr_encap[i]);
}
printf("\n");
} else if (req->nhr_type == NH_TUNNEL) {
nh_print_newline_header();
printf("Oif:%d Len:%d Flags %s Data:", req->nhr_encap_oif_id,
Expand All @@ -233,23 +237,33 @@ vr_nexthop_req_process(void *s_req)
}
} else if (req->nhr_type == NH_VRF_TRANSLATE) {
nh_print_newline_header();
printf("Vrf:%d\n", req->nhr_vrf);
printf("Vrf:%d\n", ' ', req->nhr_vrf);
} else if (req->nhr_type == NH_COMPOSITE) {
nh_print_newline_header();
printf("Sub NH(label):");
for (i = 0; i < req->nhr_nh_list_size; i++) {
printf(" %d", req->nhr_nh_list[i]);
if (printed > 60) {
nh_print_newline_header();
printf("%14c", ' ');
printed = 0;
}
printed += printf(" %d", req->nhr_nh_list[i]);
if (req->nhr_label_list[i] >= 0)
printf("(%d)", req->nhr_label_list[i]);
printed += printf("(%d)", req->nhr_label_list[i]);
}

if (req->nhr_nh_count &&
(req->nhr_nh_count - req->nhr_nh_list_size)) {
printf(" and %u more components...\n",
req->nhr_nh_count - req->nhr_nh_list_size);
}
printf("\n");
}

if (command == SANDESH_OP_DUMP) {
dump_marker = req->nhr_id;
}

printf("\n");
printf("\n\n");
}

void
Expand Down

0 comments on commit 593f6a9

Please sign in to comment.