mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 07:03:07 +00:00
pimd: Add accidently missed code during upstreaming process
There was some code missed during the upstreaming process due to code squash. Identify and put into a commit to keep code consistent and correct. Signed-off-by: Satheesh Kumar K <sathk@cumulusnetworks.com> Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com> Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
a054f6d73e
commit
17823cdd2c
269
pimd/pim_cmd.c
269
pimd/pim_cmd.c
@ -909,7 +909,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
|
|||||||
|
|
||||||
static void pim_show_interfaces_single(struct pim_instance *pim,
|
static void pim_show_interfaces_single(struct pim_instance *pim,
|
||||||
struct vty *vty, const char *ifname,
|
struct vty *vty, const char *ifname,
|
||||||
bool uj)
|
bool mlag, bool uj)
|
||||||
{
|
{
|
||||||
struct in_addr ifaddr;
|
struct in_addr ifaddr;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
@ -952,6 +952,9 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
|
|||||||
if (!pim_ifp)
|
if (!pim_ifp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (mlag == true && pim_ifp->activeactive == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
|
if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1380,7 +1383,7 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
|
static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
|
||||||
bool uj)
|
bool mlag, bool uj)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_interface *pim_ifp;
|
||||||
@ -1400,6 +1403,9 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
|
|||||||
if (!pim_ifp)
|
if (!pim_ifp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (mlag == true && pim_ifp->activeactive == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
pim_nbrs = pim_ifp->pim_neighbor_list->count;
|
pim_nbrs = pim_ifp->pim_neighbor_list->count;
|
||||||
pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
|
pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
|
||||||
fhr = 0;
|
fhr = 0;
|
||||||
@ -4295,6 +4301,113 @@ DEFUN (show_ip_igmp_statistics,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (show_ip_pim_mlag_summary,
|
||||||
|
show_ip_pim_mlag_summary_cmd,
|
||||||
|
"show ip pim mlag summary [json]",
|
||||||
|
SHOW_STR
|
||||||
|
IP_STR
|
||||||
|
PIM_STR
|
||||||
|
"MLAG\n"
|
||||||
|
"status and stats\n"
|
||||||
|
JSON_STR)
|
||||||
|
{
|
||||||
|
bool uj = use_json(argc, argv);
|
||||||
|
char role_buf[MLAG_ROLE_STRSIZE];
|
||||||
|
char addr_buf[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (uj) {
|
||||||
|
json_object *json = NULL;
|
||||||
|
json_object *json_stat = NULL;
|
||||||
|
|
||||||
|
json = json_object_new_object();
|
||||||
|
if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
||||||
|
json_object_boolean_true_add(json, "mlagConnUp");
|
||||||
|
if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
||||||
|
json_object_boolean_true_add(json, "mlagPeerConnUp");
|
||||||
|
if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
||||||
|
json_object_boolean_true_add(json, "mlagPeerZebraUp");
|
||||||
|
json_object_string_add(json, "mlagRole",
|
||||||
|
mlag_role2str(router->mlag_role,
|
||||||
|
role_buf, sizeof(role_buf)));
|
||||||
|
inet_ntop(AF_INET, &router->local_vtep_ip,
|
||||||
|
addr_buf, INET_ADDRSTRLEN);
|
||||||
|
json_object_string_add(json, "localVtepIp", addr_buf);
|
||||||
|
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
||||||
|
addr_buf, INET_ADDRSTRLEN);
|
||||||
|
json_object_string_add(json, "anycastVtepIp", addr_buf);
|
||||||
|
json_object_string_add(json, "peerlinkRif",
|
||||||
|
router->peerlink_rif);
|
||||||
|
|
||||||
|
json_stat = json_object_new_object();
|
||||||
|
json_object_int_add(json_stat, "mlagConnFlaps",
|
||||||
|
router->mlag_stats.mlagd_session_downs);
|
||||||
|
json_object_int_add(json_stat, "mlagPeerConnFlaps",
|
||||||
|
router->mlag_stats.peer_session_downs);
|
||||||
|
json_object_int_add(json_stat, "mlagPeerZebraFlaps",
|
||||||
|
router->mlag_stats.peer_zebra_downs);
|
||||||
|
json_object_int_add(json_stat, "mrouteAddRx",
|
||||||
|
router->mlag_stats.msg.mroute_add_rx);
|
||||||
|
json_object_int_add(json_stat, "mrouteAddTx",
|
||||||
|
router->mlag_stats.msg.mroute_add_tx);
|
||||||
|
json_object_int_add(json_stat, "mrouteDelRx",
|
||||||
|
router->mlag_stats.msg.mroute_del_rx);
|
||||||
|
json_object_int_add(json_stat, "mrouteDelTx",
|
||||||
|
router->mlag_stats.msg.mroute_del_tx);
|
||||||
|
json_object_int_add(json_stat, "mlagStatusUpdates",
|
||||||
|
router->mlag_stats.msg.mlag_status_updates);
|
||||||
|
json_object_int_add(json_stat, "peerZebraStatusUpdates",
|
||||||
|
router->mlag_stats.msg.peer_zebra_status_updates);
|
||||||
|
json_object_int_add(json_stat, "pimStatusUpdates",
|
||||||
|
router->mlag_stats.msg.pim_status_updates);
|
||||||
|
json_object_int_add(json_stat, "vxlanUpdates",
|
||||||
|
router->mlag_stats.msg.vxlan_updates);
|
||||||
|
json_object_object_add(json, "connStats", json_stat);
|
||||||
|
|
||||||
|
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||||||
|
json, JSON_C_TO_STRING_PRETTY));
|
||||||
|
json_object_free(json);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
vty_out(vty, "MLAG daemon connection: %s\n",
|
||||||
|
(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
||||||
|
? "up" : "down");
|
||||||
|
vty_out(vty, "MLAG peer state: %s\n",
|
||||||
|
(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
||||||
|
? "up" : "down");
|
||||||
|
vty_out(vty, "Zebra peer state: %s\n",
|
||||||
|
(router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
||||||
|
? "up" : "down");
|
||||||
|
vty_out(vty, "MLAG role: %s\n",
|
||||||
|
mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
|
||||||
|
inet_ntop(AF_INET, &router->local_vtep_ip,
|
||||||
|
addr_buf, INET_ADDRSTRLEN);
|
||||||
|
vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
|
||||||
|
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
||||||
|
addr_buf, INET_ADDRSTRLEN);
|
||||||
|
vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
|
||||||
|
vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
|
||||||
|
vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
|
||||||
|
router->mlag_stats.mlagd_session_downs,
|
||||||
|
router->mlag_stats.peer_session_downs,
|
||||||
|
router->mlag_stats.peer_zebra_downs);
|
||||||
|
vty_out(vty, "Message Statistics:\n");
|
||||||
|
vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
|
||||||
|
router->mlag_stats.msg.mroute_add_rx,
|
||||||
|
router->mlag_stats.msg.mroute_add_tx);
|
||||||
|
vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
|
||||||
|
router->mlag_stats.msg.mroute_del_rx,
|
||||||
|
router->mlag_stats.msg.mroute_del_tx);
|
||||||
|
vty_out(vty, " peer zebra status updates: %d\n",
|
||||||
|
router->mlag_stats.msg.peer_zebra_status_updates);
|
||||||
|
vty_out(vty, " PIM status updates: %d\n",
|
||||||
|
router->mlag_stats.msg.pim_status_updates);
|
||||||
|
vty_out(vty, " VxLAN updates: %d\n",
|
||||||
|
router->mlag_stats.msg.vxlan_updates);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN (show_ip_pim_assert,
|
DEFUN (show_ip_pim_assert,
|
||||||
show_ip_pim_assert_cmd,
|
show_ip_pim_assert_cmd,
|
||||||
"show ip pim [vrf NAME] assert",
|
"show ip pim [vrf NAME] assert",
|
||||||
@ -4377,10 +4490,11 @@ DEFUN (show_ip_pim_assert_winner_metric,
|
|||||||
|
|
||||||
DEFUN (show_ip_pim_interface,
|
DEFUN (show_ip_pim_interface,
|
||||||
show_ip_pim_interface_cmd,
|
show_ip_pim_interface_cmd,
|
||||||
"show ip pim [vrf NAME] interface [detail|WORD] [json]",
|
"show ip pim [mlag] [vrf NAME] interface [detail|WORD] [json]",
|
||||||
SHOW_STR
|
SHOW_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
PIM_STR
|
PIM_STR
|
||||||
|
"MLAG\n"
|
||||||
VRF_CMD_HELP_STR
|
VRF_CMD_HELP_STR
|
||||||
"PIM interface information\n"
|
"PIM interface information\n"
|
||||||
"Detailed output\n"
|
"Detailed output\n"
|
||||||
@ -4390,36 +4504,47 @@ DEFUN (show_ip_pim_interface,
|
|||||||
int idx = 2;
|
int idx = 2;
|
||||||
struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
|
struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
|
||||||
bool uj = use_json(argc, argv);
|
bool uj = use_json(argc, argv);
|
||||||
|
bool mlag = false;
|
||||||
|
|
||||||
if (!vrf)
|
if (!vrf)
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
if (argv_find(argv, argc, "mlag", &idx))
|
||||||
|
mlag = true;
|
||||||
|
|
||||||
if (argv_find(argv, argc, "WORD", &idx)
|
if (argv_find(argv, argc, "WORD", &idx)
|
||||||
|| argv_find(argv, argc, "detail", &idx))
|
|| argv_find(argv, argc, "detail", &idx))
|
||||||
pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
|
pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, mlag,
|
||||||
|
uj);
|
||||||
else
|
else
|
||||||
pim_show_interfaces(vrf->info, vty, uj);
|
pim_show_interfaces(vrf->info, vty, mlag, uj);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (show_ip_pim_interface_vrf_all,
|
DEFUN (show_ip_pim_interface_vrf_all,
|
||||||
show_ip_pim_interface_vrf_all_cmd,
|
show_ip_pim_interface_vrf_all_cmd,
|
||||||
"show ip pim vrf all interface [detail|WORD] [json]",
|
"show ip pim [mlag] vrf all interface [detail|WORD] [json]",
|
||||||
SHOW_STR
|
SHOW_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
PIM_STR
|
PIM_STR
|
||||||
|
"MLAG\n"
|
||||||
VRF_CMD_HELP_STR
|
VRF_CMD_HELP_STR
|
||||||
"PIM interface information\n"
|
"PIM interface information\n"
|
||||||
"Detailed output\n"
|
"Detailed output\n"
|
||||||
"interface name\n"
|
"interface name\n"
|
||||||
JSON_STR)
|
JSON_STR)
|
||||||
{
|
{
|
||||||
int idx = 6;
|
int idx = 2;
|
||||||
bool uj = use_json(argc, argv);
|
bool uj = use_json(argc, argv);
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
bool mlag = false;
|
||||||
|
|
||||||
|
if (argv_find(argv, argc, "mlag", &idx))
|
||||||
|
mlag = true;
|
||||||
|
|
||||||
|
idx = 6;
|
||||||
if (uj)
|
if (uj)
|
||||||
vty_out(vty, "{ ");
|
vty_out(vty, "{ ");
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||||
@ -4433,9 +4558,9 @@ DEFUN (show_ip_pim_interface_vrf_all,
|
|||||||
if (argv_find(argv, argc, "WORD", &idx)
|
if (argv_find(argv, argc, "WORD", &idx)
|
||||||
|| argv_find(argv, argc, "detail", &idx))
|
|| argv_find(argv, argc, "detail", &idx))
|
||||||
pim_show_interfaces_single(vrf->info, vty,
|
pim_show_interfaces_single(vrf->info, vty,
|
||||||
argv[idx]->arg, uj);
|
argv[idx]->arg, mlag, uj);
|
||||||
else
|
else
|
||||||
pim_show_interfaces(vrf->info, vty, uj);
|
pim_show_interfaces(vrf->info, vty, mlag, uj);
|
||||||
}
|
}
|
||||||
if (uj)
|
if (uj)
|
||||||
vty_out(vty, "}\n");
|
vty_out(vty, "}\n");
|
||||||
@ -4625,113 +4750,6 @@ DEFUN (show_ip_pim_local_membership,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (show_ip_pim_mlag_summary,
|
|
||||||
show_ip_pim_mlag_summary_cmd,
|
|
||||||
"show ip pim mlag summary [json]",
|
|
||||||
SHOW_STR
|
|
||||||
IP_STR
|
|
||||||
PIM_STR
|
|
||||||
"MLAG\n"
|
|
||||||
"status and stats\n"
|
|
||||||
JSON_STR)
|
|
||||||
{
|
|
||||||
bool uj = use_json(argc, argv);
|
|
||||||
char role_buf[MLAG_ROLE_STRSIZE];
|
|
||||||
char addr_buf[INET_ADDRSTRLEN];
|
|
||||||
|
|
||||||
if (uj) {
|
|
||||||
json_object *json = NULL;
|
|
||||||
json_object *json_stat = NULL;
|
|
||||||
|
|
||||||
json = json_object_new_object();
|
|
||||||
if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
|
||||||
json_object_boolean_true_add(json, "mlagConnUp");
|
|
||||||
if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
|
||||||
json_object_boolean_true_add(json, "mlagPeerConnUp");
|
|
||||||
if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
|
||||||
json_object_boolean_true_add(json, "mlagPeerZebraUp");
|
|
||||||
json_object_string_add(json, "mlagRole",
|
|
||||||
mlag_role2str(router->mlag_role,
|
|
||||||
role_buf, sizeof(role_buf)));
|
|
||||||
inet_ntop(AF_INET, &router->local_vtep_ip,
|
|
||||||
addr_buf, INET_ADDRSTRLEN);
|
|
||||||
json_object_string_add(json, "localVtepIp", addr_buf);
|
|
||||||
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
|
||||||
addr_buf, INET_ADDRSTRLEN);
|
|
||||||
json_object_string_add(json, "anycastVtepIp", addr_buf);
|
|
||||||
json_object_string_add(json, "peerlinkRif",
|
|
||||||
router->peerlink_rif);
|
|
||||||
|
|
||||||
json_stat = json_object_new_object();
|
|
||||||
json_object_int_add(json_stat, "mlagConnFlaps",
|
|
||||||
router->mlag_stats.mlagd_session_downs);
|
|
||||||
json_object_int_add(json_stat, "mlagPeerConnFlaps",
|
|
||||||
router->mlag_stats.peer_session_downs);
|
|
||||||
json_object_int_add(json_stat, "mlagPeerZebraFlaps",
|
|
||||||
router->mlag_stats.peer_zebra_downs);
|
|
||||||
json_object_int_add(json_stat, "mrouteAddRx",
|
|
||||||
router->mlag_stats.msg.mroute_add_rx);
|
|
||||||
json_object_int_add(json_stat, "mrouteAddTx",
|
|
||||||
router->mlag_stats.msg.mroute_add_tx);
|
|
||||||
json_object_int_add(json_stat, "mrouteDelRx",
|
|
||||||
router->mlag_stats.msg.mroute_del_rx);
|
|
||||||
json_object_int_add(json_stat, "mrouteDelTx",
|
|
||||||
router->mlag_stats.msg.mroute_del_tx);
|
|
||||||
json_object_int_add(json_stat, "mlagStatusUpdates",
|
|
||||||
router->mlag_stats.msg.mlag_status_updates);
|
|
||||||
json_object_int_add(json_stat, "peerZebraStatusUpdates",
|
|
||||||
router->mlag_stats.msg.peer_zebra_status_updates);
|
|
||||||
json_object_int_add(json_stat, "pimStatusUpdates",
|
|
||||||
router->mlag_stats.msg.pim_status_updates);
|
|
||||||
json_object_int_add(json_stat, "vxlanUpdates",
|
|
||||||
router->mlag_stats.msg.vxlan_updates);
|
|
||||||
json_object_object_add(json, "connStats", json_stat);
|
|
||||||
|
|
||||||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
|
||||||
json, JSON_C_TO_STRING_PRETTY));
|
|
||||||
json_object_free(json);
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
vty_out(vty, "MLAG daemon connection: %s\n",
|
|
||||||
(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
|
||||||
? "up" : "down");
|
|
||||||
vty_out(vty, "MLAG peer state: %s\n",
|
|
||||||
(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
|
||||||
? "up" : "down");
|
|
||||||
vty_out(vty, "Zebra peer state: %s\n",
|
|
||||||
(router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
|
||||||
? "up" : "down");
|
|
||||||
vty_out(vty, "MLAG role: %s\n",
|
|
||||||
mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
|
|
||||||
inet_ntop(AF_INET, &router->local_vtep_ip,
|
|
||||||
addr_buf, INET_ADDRSTRLEN);
|
|
||||||
vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
|
|
||||||
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
|
||||||
addr_buf, INET_ADDRSTRLEN);
|
|
||||||
vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
|
|
||||||
vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
|
|
||||||
vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
|
|
||||||
router->mlag_stats.mlagd_session_downs,
|
|
||||||
router->mlag_stats.peer_session_downs,
|
|
||||||
router->mlag_stats.peer_zebra_downs);
|
|
||||||
vty_out(vty, "Message Statistics:\n");
|
|
||||||
vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
|
|
||||||
router->mlag_stats.msg.mroute_add_rx,
|
|
||||||
router->mlag_stats.msg.mroute_add_tx);
|
|
||||||
vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
|
|
||||||
router->mlag_stats.msg.mroute_del_rx,
|
|
||||||
router->mlag_stats.msg.mroute_del_tx);
|
|
||||||
vty_out(vty, " peer zebra status updates: %d\n",
|
|
||||||
router->mlag_stats.msg.peer_zebra_status_updates);
|
|
||||||
vty_out(vty, " PIM status updates: %d\n",
|
|
||||||
router->mlag_stats.msg.pim_status_updates);
|
|
||||||
vty_out(vty, " VxLAN updates: %d\n",
|
|
||||||
router->mlag_stats.msg.vxlan_updates);
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pim_show_mlag_up_entry_detail(struct vrf *vrf,
|
static void pim_show_mlag_up_entry_detail(struct vrf *vrf,
|
||||||
struct vty *vty, struct pim_upstream *up,
|
struct vty *vty, struct pim_upstream *up,
|
||||||
char *src_str, char *grp_str, json_object *json)
|
char *src_str, char *grp_str, json_object *json)
|
||||||
@ -8035,13 +8053,13 @@ DEFPY_HIDDEN (pim_test_sg_keepalive,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_HIDDEN (interface_ip_pim_activeactive,
|
DEFPY (interface_ip_pim_activeactive,
|
||||||
interface_ip_pim_activeactive_cmd,
|
interface_ip_pim_activeactive_cmd,
|
||||||
"[no$no] ip pim active-active",
|
"[no$no] ip pim active-active",
|
||||||
NO_STR
|
NO_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
PIM_STR
|
PIM_STR
|
||||||
"Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
|
"Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_interface *pim_ifp;
|
||||||
@ -8051,6 +8069,11 @@ DEFPY_HIDDEN (interface_ip_pim_activeactive,
|
|||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (PIM_DEBUG_MLAG)
|
||||||
|
zlog_debug("%sConfiguring PIM active-active on Interface: %s",
|
||||||
|
no ? "Un-":" ", ifp->name);
|
||||||
|
|
||||||
pim_ifp = ifp->info;
|
pim_ifp = ifp->info;
|
||||||
if (no)
|
if (no)
|
||||||
pim_if_unconfigure_mlag_dualactive(pim_ifp);
|
pim_if_unconfigure_mlag_dualactive(pim_ifp);
|
||||||
|
@ -1073,6 +1073,9 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vxlan term mroutes use ipmr-lo as local member to
|
||||||
|
* pull down multicast vxlan tunnel traffic
|
||||||
|
*/
|
||||||
up_flags = is_vxlan ? PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM :
|
up_flags = is_vxlan ? PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM :
|
||||||
PIM_UPSTREAM_FLAG_MASK_SRC_IGMP;
|
PIM_UPSTREAM_FLAG_MASK_SRC_IGMP;
|
||||||
ch = pim_ifchannel_add(ifp, sg, 0, up_flags);
|
ch = pim_ifchannel_add(ifp, sg, 0, up_flags);
|
||||||
|
@ -312,14 +312,6 @@ static void pim_mlag_up_peer_del_all(void)
|
|||||||
list_delete(&temp);
|
list_delete(&temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pim_mlag_signal_zpthread(void)
|
|
||||||
{
|
|
||||||
/* XXX - This is a temporary stub; the MLAG thread code is planned for
|
|
||||||
* a separate commit
|
|
||||||
*/
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send upstream entry to the local MLAG daemon (which will subsequently
|
/* Send upstream entry to the local MLAG daemon (which will subsequently
|
||||||
* send it to the peer MLAG switch).
|
* send it to the peer MLAG switch).
|
||||||
*/
|
*/
|
||||||
@ -872,7 +864,7 @@ static int pim_mlag_deregister_handler(struct thread *thread)
|
|||||||
void pim_mlag_deregister(void)
|
void pim_mlag_deregister(void)
|
||||||
{
|
{
|
||||||
/* if somebody still interested in the MLAG channel skip de-reg */
|
/* if somebody still interested in the MLAG channel skip de-reg */
|
||||||
if (router->pim_mlag_intf_cnt)
|
if (router->pim_mlag_intf_cnt || pim_vxlan_do_mlag_reg())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* not registered; nothing do */
|
/* not registered; nothing do */
|
||||||
@ -890,10 +882,6 @@ void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp)
|
|||||||
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == true)
|
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PIM_DEBUG_MLAG)
|
|
||||||
zlog_debug("%s: Configuring active-active on Interface: %s",
|
|
||||||
__func__, "NULL");
|
|
||||||
|
|
||||||
pim_ifp->activeactive = true;
|
pim_ifp->activeactive = true;
|
||||||
if (pim_ifp->pim)
|
if (pim_ifp->pim)
|
||||||
pim_ifp->pim->inst_mlag_intf_cnt++;
|
pim_ifp->pim->inst_mlag_intf_cnt++;
|
||||||
@ -919,10 +907,6 @@ void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
|
|||||||
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == false)
|
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PIM_DEBUG_MLAG)
|
|
||||||
zlog_debug("%s: UnConfiguring active-active on Interface: %s",
|
|
||||||
__func__, "NULL");
|
|
||||||
|
|
||||||
pim_ifp->activeactive = false;
|
pim_ifp->activeactive = false;
|
||||||
pim_ifp->pim->inst_mlag_intf_cnt--;
|
pim_ifp->pim->inst_mlag_intf_cnt--;
|
||||||
|
|
||||||
@ -939,6 +923,7 @@ void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
|
|||||||
* De-register to Zebra
|
* De-register to Zebra
|
||||||
*/
|
*/
|
||||||
pim_mlag_deregister();
|
pim_mlag_deregister();
|
||||||
|
pim_mlag_param_reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,12 @@ extern void pim_mlag_deregister(void);
|
|||||||
extern int pim_zebra_mlag_process_up(void);
|
extern int pim_zebra_mlag_process_up(void);
|
||||||
extern int pim_zebra_mlag_process_down(void);
|
extern int pim_zebra_mlag_process_down(void);
|
||||||
extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len);
|
extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len);
|
||||||
|
|
||||||
|
/* pm_zpthread.c */
|
||||||
|
extern int pim_mlag_signal_zpthread(void);
|
||||||
|
extern void pim_zpthread_init(void);
|
||||||
|
extern void pim_zpthread_terminate(void);
|
||||||
|
|
||||||
extern void pim_mlag_up_local_add(struct pim_instance *pim,
|
extern void pim_mlag_up_local_add(struct pim_instance *pim,
|
||||||
struct pim_upstream *upstream);
|
struct pim_upstream *upstream);
|
||||||
extern void pim_mlag_up_local_del(struct pim_instance *pim,
|
extern void pim_mlag_up_local_del(struct pim_instance *pim,
|
||||||
|
@ -33,9 +33,6 @@
|
|||||||
#include "pim_time.h"
|
#include "pim_time.h"
|
||||||
#include "pim_vxlan.h"
|
#include "pim_vxlan.h"
|
||||||
|
|
||||||
// struct list *pim_channel_oil_list = NULL;
|
|
||||||
// struct hash *pim_channel_oil_hash = NULL;
|
|
||||||
|
|
||||||
static void pim_channel_update_mute(struct channel_oil *c_oil);
|
static void pim_channel_update_mute(struct channel_oil *c_oil);
|
||||||
|
|
||||||
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
|
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
|
||||||
@ -174,7 +171,7 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
|
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
if (PIM_DEBUG_MROUTE) {
|
if (PIM_DEBUG_MROUTE) {
|
||||||
struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp,
|
struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp,
|
||||||
|
@ -130,7 +130,7 @@ void pim_channel_oil_change_iif(struct pim_instance *pim,
|
|||||||
struct channel_oil *c_oil, int input_vif_index,
|
struct channel_oil *c_oil, int input_vif_index,
|
||||||
const char *name);
|
const char *name);
|
||||||
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
|
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
|
||||||
int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif,
|
int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif,
|
||||||
uint32_t proto_mask, const char *caller);
|
uint32_t proto_mask, const char *caller);
|
||||||
@ -146,6 +146,6 @@ void pim_channel_update_oif_mute(struct channel_oil *c_oil,
|
|||||||
|
|
||||||
void pim_channel_oil_upstream_deref(struct channel_oil *c_oil);
|
void pim_channel_oil_upstream_deref(struct channel_oil *c_oil);
|
||||||
void pim_channel_del_inherited_oif(struct channel_oil *c_oil,
|
void pim_channel_del_inherited_oif(struct channel_oil *c_oil,
|
||||||
struct interface *oif, const char *caller);
|
struct interface *oif, const char *caller);
|
||||||
|
|
||||||
#endif /* PIM_OIL_H */
|
#endif /* PIM_OIL_H */
|
||||||
|
@ -117,6 +117,11 @@ int pim_debug_config_write(struct vty *vty)
|
|||||||
++writes;
|
++writes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PIM_DEBUG_MLAG) {
|
||||||
|
vty_out(vty, "debug pim mlag\n");
|
||||||
|
++writes;
|
||||||
|
}
|
||||||
|
|
||||||
if (PIM_DEBUG_BSM) {
|
if (PIM_DEBUG_BSM) {
|
||||||
vty_out(vty, "debug pim bsm\n");
|
vty_out(vty, "debug pim bsm\n");
|
||||||
++writes;
|
++writes;
|
||||||
|
225
pimd/pim_zpthread.c
Normal file
225
pimd/pim_zpthread.c
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* PIM for Quagga
|
||||||
|
* Copyright (C) 2008 Everton da Silva Marques
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; see the file COPYING; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include <lib/log.h>
|
||||||
|
#include <lib/lib_errors.h>
|
||||||
|
|
||||||
|
#include "pimd.h"
|
||||||
|
#include "pim_mlag.h"
|
||||||
|
#include "pim_zebra.h"
|
||||||
|
|
||||||
|
extern struct zclient *zclient;
|
||||||
|
|
||||||
|
#define PIM_MLAG_POST_LIMIT 100
|
||||||
|
|
||||||
|
int32_t mlag_bulk_cnt;
|
||||||
|
|
||||||
|
static void pim_mlag_zebra_fill_header(enum mlag_msg_type msg_type)
|
||||||
|
{
|
||||||
|
uint32_t fill_msg_type = msg_type;
|
||||||
|
uint16_t data_len;
|
||||||
|
uint16_t msg_cnt = 1;
|
||||||
|
|
||||||
|
if (msg_type == MLAG_MSG_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (msg_type) {
|
||||||
|
case MLAG_REGISTER:
|
||||||
|
case MLAG_DEREGISTER:
|
||||||
|
data_len = sizeof(struct mlag_msg);
|
||||||
|
break;
|
||||||
|
case MLAG_MROUTE_ADD:
|
||||||
|
data_len = sizeof(struct mlag_mroute_add);
|
||||||
|
fill_msg_type = MLAG_MROUTE_ADD_BULK;
|
||||||
|
break;
|
||||||
|
case MLAG_MROUTE_DEL:
|
||||||
|
data_len = sizeof(struct mlag_mroute_del);
|
||||||
|
fill_msg_type = MLAG_MROUTE_DEL_BULK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
data_len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_reset(router->mlag_stream);
|
||||||
|
/* ADD Hedaer */
|
||||||
|
stream_putl(router->mlag_stream, fill_msg_type);
|
||||||
|
/*
|
||||||
|
* In case of Bulk actual size & msg_cnt will be updated
|
||||||
|
* just before writing onto zebra
|
||||||
|
*/
|
||||||
|
stream_putw(router->mlag_stream, data_len);
|
||||||
|
stream_putw(router->mlag_stream, msg_cnt);
|
||||||
|
|
||||||
|
if (PIM_DEBUG_MLAG)
|
||||||
|
zlog_debug(":%s: msg_type: %d/%d len %d",
|
||||||
|
__func__, msg_type, fill_msg_type, data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pim_mlag_zebra_flush_buffer(void)
|
||||||
|
{
|
||||||
|
uint32_t msg_type;
|
||||||
|
|
||||||
|
/* Stream had bulk messages update the Hedaer */
|
||||||
|
if (mlag_bulk_cnt > 1) {
|
||||||
|
/*
|
||||||
|
* No need to reset the pointer, below api reads from data[0]
|
||||||
|
*/
|
||||||
|
STREAM_GETL(router->mlag_stream, msg_type);
|
||||||
|
if (msg_type == MLAG_MROUTE_ADD_BULK) {
|
||||||
|
stream_putw_at(
|
||||||
|
router->mlag_stream, 4,
|
||||||
|
(mlag_bulk_cnt * sizeof(struct mlag_mroute_add)));
|
||||||
|
stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
|
||||||
|
} else if (msg_type == MLAG_MROUTE_DEL_BULK) {
|
||||||
|
stream_putw_at(
|
||||||
|
router->mlag_stream, 4,
|
||||||
|
(mlag_bulk_cnt * sizeof(struct mlag_mroute_del)));
|
||||||
|
stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
|
||||||
|
} else {
|
||||||
|
flog_err(EC_LIB_ZAPI_ENCODE,
|
||||||
|
"unknown bulk message type %d bulk_count %d",
|
||||||
|
msg_type, mlag_bulk_cnt);
|
||||||
|
stream_reset(router->mlag_stream);
|
||||||
|
mlag_bulk_cnt = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zclient_send_mlag_data(zclient, router->mlag_stream);
|
||||||
|
stream_failure:
|
||||||
|
stream_reset(router->mlag_stream);
|
||||||
|
mlag_bulk_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only ROUTE add & Delete will be bulked.
|
||||||
|
* Buffer will be flushed, when
|
||||||
|
* 1) there were no messages in the queue
|
||||||
|
* 2) Curr_msg_type != prev_msg_type
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void pim_mlag_zebra_check_for_buffer_flush(uint32_t curr_msg_type,
|
||||||
|
uint32_t prev_msg_type)
|
||||||
|
{
|
||||||
|
/* First Message, keep bulking */
|
||||||
|
if (prev_msg_type == MLAG_MSG_NONE) {
|
||||||
|
mlag_bulk_cnt = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*msg type is route add & delete, keep bulking */
|
||||||
|
if (curr_msg_type == prev_msg_type
|
||||||
|
&& (curr_msg_type == MLAG_MROUTE_ADD
|
||||||
|
|| curr_msg_type == MLAG_MROUTE_DEL)) {
|
||||||
|
mlag_bulk_cnt++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pim_mlag_zebra_flush_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Thsi thread reads the clients data from the Gloabl queue and encodes with
|
||||||
|
* protobuf and pass on to the MLAG socket.
|
||||||
|
*/
|
||||||
|
static int pim_mlag_zthread_handler(struct thread *event)
|
||||||
|
{
|
||||||
|
struct stream *read_s;
|
||||||
|
uint32_t wr_count = 0;
|
||||||
|
uint32_t prev_msg_type = MLAG_MSG_NONE;
|
||||||
|
uint32_t curr_msg_type = MLAG_MSG_NONE;
|
||||||
|
|
||||||
|
router->zpthread_mlag_write = NULL;
|
||||||
|
wr_count = stream_fifo_count_safe(router->mlag_fifo);
|
||||||
|
|
||||||
|
if (PIM_DEBUG_MLAG)
|
||||||
|
zlog_debug(":%s: Processing MLAG write, %d messages in queue",
|
||||||
|
__func__, wr_count);
|
||||||
|
|
||||||
|
if (wr_count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (wr_count = 0; wr_count < PIM_MLAG_POST_LIMIT; wr_count++) {
|
||||||
|
/* FIFO is empty,wait for teh message to be add */
|
||||||
|
if (stream_fifo_count_safe(router->mlag_fifo) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
read_s = stream_fifo_pop_safe(router->mlag_fifo);
|
||||||
|
if (!read_s) {
|
||||||
|
zlog_debug(":%s: Got a NULL Messages, some thing wrong",
|
||||||
|
__func__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
STREAM_GETL(read_s, curr_msg_type);
|
||||||
|
/*
|
||||||
|
* Check for Buffer Overflow,
|
||||||
|
* MLAG Can't process more than 'PIM_MLAG_BUF_LIMIT' bytes
|
||||||
|
*/
|
||||||
|
if (router->mlag_stream->endp + read_s->endp + ZEBRA_HEADER_SIZE
|
||||||
|
> MLAG_BUF_LIMIT)
|
||||||
|
pim_mlag_zebra_flush_buffer();
|
||||||
|
|
||||||
|
pim_mlag_zebra_check_for_buffer_flush(curr_msg_type,
|
||||||
|
prev_msg_type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First message to Buffer, fill the Header
|
||||||
|
*/
|
||||||
|
if (router->mlag_stream->endp == 0)
|
||||||
|
pim_mlag_zebra_fill_header(curr_msg_type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add the data now
|
||||||
|
*/
|
||||||
|
stream_put(router->mlag_stream, read_s->data + read_s->getp,
|
||||||
|
read_s->endp - read_s->getp);
|
||||||
|
|
||||||
|
stream_free(read_s);
|
||||||
|
prev_msg_type = curr_msg_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_failure:
|
||||||
|
/*
|
||||||
|
* we are here , because
|
||||||
|
* 1. Queue might be empty
|
||||||
|
* 2. we crossed the max Q Read limit
|
||||||
|
* In any acse flush the buffer towards zebra
|
||||||
|
*/
|
||||||
|
pim_mlag_zebra_flush_buffer();
|
||||||
|
|
||||||
|
if (wr_count >= PIM_MLAG_POST_LIMIT)
|
||||||
|
pim_mlag_signal_zpthread();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int pim_mlag_signal_zpthread(void)
|
||||||
|
{
|
||||||
|
if (router->master) {
|
||||||
|
if (PIM_DEBUG_MLAG)
|
||||||
|
zlog_debug(":%s: Scheduling PIM MLAG write Thread",
|
||||||
|
__func__);
|
||||||
|
thread_add_event(router->master, pim_mlag_zthread_handler, NULL,
|
||||||
|
0, &router->zpthread_mlag_write);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
@ -102,6 +102,8 @@ void pim_router_init(void)
|
|||||||
router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
|
router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
|
||||||
router->register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
|
router->register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
|
||||||
router->vrf_id = VRF_DEFAULT;
|
router->vrf_id = VRF_DEFAULT;
|
||||||
|
router->pim_mlag_intf_cnt = 0;
|
||||||
|
router->connected_to_mlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pim_router_terminate(void)
|
void pim_router_terminate(void)
|
||||||
|
@ -63,6 +63,7 @@ pimd_libpim_a_SOURCES = \
|
|||||||
pimd/pim_zebra.c \
|
pimd/pim_zebra.c \
|
||||||
pimd/pim_zlookup.c \
|
pimd/pim_zlookup.c \
|
||||||
pimd/pim_vxlan.c \
|
pimd/pim_vxlan.c \
|
||||||
|
pimd/pim_zpthread.c \
|
||||||
pimd/pimd.c \
|
pimd/pimd.c \
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ extern uint32_t mlag_rd_buf_offset;
|
|||||||
|
|
||||||
static inline void zebra_mlag_reset_read_buffer(void)
|
static inline void zebra_mlag_reset_read_buffer(void)
|
||||||
{
|
{
|
||||||
|
memset(mlag_wr_buffer, 0, ZEBRA_MLAG_BUF_LIMIT);
|
||||||
mlag_rd_buf_offset = 0;
|
mlag_rd_buf_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,8 @@ static int zebra_mlag_read(struct thread *thread)
|
|||||||
uint32_t h_msglen;
|
uint32_t h_msglen;
|
||||||
uint32_t tot_len, curr_len = mlag_rd_buf_offset;
|
uint32_t tot_len, curr_len = mlag_rd_buf_offset;
|
||||||
|
|
||||||
|
zrouter.mlag_info.t_read = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Received message in sock_stream looks like below
|
* Received message in sock_stream looks like below
|
||||||
* | len-1 (4 Bytes) | payload-1 (len-1) |
|
* | len-1 (4 Bytes) | payload-1 (len-1) |
|
||||||
|
Loading…
Reference in New Issue
Block a user