struct vty *vty;
json_object *json;
struct zebra_vrf *zvrf;
+ bool use_json;
};
/* print a L3 VNI hash entry in detail*/
{
struct vty *vty = NULL;
zebra_l3vni_t *zl3vni = NULL;
- json_object *json = NULL;
+ json_object *json_array = NULL;
bool use_json = false;
struct zvni_evpn_show *zes = data;
vty = zes->vty;
- json = zes->json;
-
- if (json)
- use_json = true;
+ json_array = zes->json;
+ use_json = zes->use_json;
zl3vni = (zebra_l3vni_t *)bucket->data;
- zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni, use_json);
- vty_out(vty, "\n");
+ zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni,
+ use_json, json_array);
+
+ if (!use_json)
+ vty_out(vty, "\n");
}
{
struct vty *vty;
zebra_vni_t *zvni;
- json_object *json = NULL;
+ json_object *json_array = NULL;
bool use_json = false;
struct zvni_evpn_show *zes = data;
vty = zes->vty;
- json = zes->json;
-
- if (json)
- use_json = true;
+ json_array = zes->json;
+ use_json = zes->use_json;
zvni = (zebra_vni_t *)bucket->data;
- zebra_vxlan_print_vni(vty, zes->zvrf, zvni->vni, use_json);
- vty_out(vty, "\n");
+ zebra_vxlan_print_vni(vty, zes->zvrf, zvni->vni, use_json, json_array);
+
+ if (!use_json)
+ vty_out(vty, "\n");
}
/*
vtep_ip = n->r_vtep_ip;
/* Mark appropriately */
UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
- n->r_vtep_ip.s_addr = 0;
+ n->r_vtep_ip.s_addr = INADDR_ANY;
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
n->ifindex = ifp->ifindex;
}
/*
* Display VNI information (VTY command handler).
+ *
+ * use_json flag indicates that output should be in JSON format.
+ * json_array is non NULL when JSON output needs to be aggregated (by the
+ * caller) and then printed, otherwise, JSON evpn vni info is printed
+ * right away.
*/
void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
- bool use_json)
+ bool use_json, json_object *json_array)
{
json_object *json = NULL;
void *args[2];
if (use_json)
json = json_object_new_object();
+
args[0] = vty;
args[1] = json;
zl3vni_print(zl3vni, (void *)args);
} else {
zvni = zvni_lookup(vni);
- if (!zvni) {
- if (use_json)
- vty_out(vty, "{}\n");
- else
- vty_out(vty, "%% VNI %u does not exist\n", vni);
- return;
- }
-
- zvni_print(zvni, (void *)args);
+ if (zvni)
+ zvni_print(zvni, (void *)args);
+ else if (!json)
+ vty_out(vty, "%% VNI %u does not exist\n", vni);
}
if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ /*
+ * Each "json" object contains info about 1 VNI.
+ * When "json_array" is non-null, we aggreggate the json output
+ * into json_array and print it as a JSON array.
+ */
+ if (json_array)
+ json_object_array_add(json_array, json);
+ else {
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
}
}
void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
bool use_json)
{
- json_object *json = NULL;
+ json_object *json_array = NULL;
struct zebra_ns *zns = NULL;
struct zvni_evpn_show zes;
if (!zns)
return;
-
if (use_json)
- json = json_object_new_object();
+ json_array = json_object_new_array();
zes.vty = vty;
- zes.json = json;
+ zes.json = json_array;
zes.zvrf = zvrf;
+ zes.use_json = use_json;
/* Display all L2-VNIs */
hash_iterate(
if (use_json) {
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ json_array, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json_array);
}
}
return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
}
+static int32_t
+zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni,
+ struct ethaddr *macaddr, uint16_t *ipa_len,
+ struct ipaddr *ip, struct in_addr *vtep_ip,
+ uint8_t *flags, uint32_t *seq)
+{
+ uint16_t l = 0;
+
+ /*
+ * Obtain each remote MACIP and process.
+ * Message contains VNI, followed by MAC followed by IP (if any)
+ * followed by remote VTEP IP.
+ */
+ memset(ip, 0, sizeof(*ip));
+ STREAM_GETL(s, *vni);
+ STREAM_GET(macaddr->octet, s, ETH_ALEN);
+ STREAM_GETL(s, *ipa_len);
+
+ if (*ipa_len) {
+ if (*ipa_len == IPV4_MAX_BYTELEN)
+ ip->ipa_type = IPADDR_V4;
+ else if (*ipa_len == IPV6_MAX_BYTELEN)
+ ip->ipa_type = IPADDR_V6;
+ else {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "ipa_len *must* be %d or %d bytes in length not %d",
+ IPV4_MAX_BYTELEN, IPV6_MAX_BYTELEN,
+ *ipa_len);
+ goto stream_failure;
+ }
+
+ STREAM_GET(&ip->ip.addr, s, *ipa_len);
+ }
+ l += 4 + ETH_ALEN + 4 + *ipa_len;
+ STREAM_GET(&vtep_ip->s_addr, s, IPV4_MAX_BYTELEN);
+ l += IPV4_MAX_BYTELEN;
+
+ if (add) {
+ STREAM_GETC(s, *flags);
+ STREAM_GETL(s, *seq);
+ l += 5;
+ }
+
+ return l;
+
+stream_failure:
+ return -1;
+}
/*
* Handle message from client to delete a remote MACIP for a VNI.
s = msg;
while (l < hdr->length) {
- /* Obtain each remote MACIP and process. */
- /* Message contains VNI, followed by MAC followed by IP (if any)
- * followed by remote VTEP IP.
- */
- memset(&ip, 0, sizeof(ip));
- STREAM_GETL(s, vni);
- STREAM_GET(&macaddr.octet, s, ETH_ALEN);
- STREAM_GETL(s, ipa_len);
- if (ipa_len) {
- ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
- : IPADDR_V6;
- STREAM_GET(&ip.ip.addr, s, ipa_len);
- }
- l += 4 + ETH_ALEN + 4 + ipa_len;
- STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
- l += IPV4_MAX_BYTELEN;
+ int res_length = zebra_vxlan_remote_macip_helper(
+ false, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, NULL,
+ NULL);
+
+ if (res_length == -1)
+ goto stream_failure;
+ l += res_length;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
s = msg;
while (l < hdr->length) {
- /* Obtain each remote MACIP and process. */
- /* Message contains VNI, followed by MAC followed by IP (if any)
- * followed by remote VTEP IP.
- */
- memset(&ip, 0, sizeof(ip));
- STREAM_GETL(s, vni);
- STREAM_GET(&macaddr.octet, s, ETH_ALEN);
- STREAM_GETL(s, ipa_len);
- if (ipa_len) {
- ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
- : IPADDR_V6;
- STREAM_GET(&ip.ip.addr, s, ipa_len);
- }
- l += 4 + ETH_ALEN + 4 + ipa_len;
- STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
- l += IPV4_MAX_BYTELEN;
+ int res_length = zebra_vxlan_remote_macip_helper(
+ true, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip,
+ &flags, &seq);
- /* Get flags - sticky mac and/or gateway mac */
- STREAM_GETC(s, flags);
- l++;
- STREAM_GETL(s, seq);
- l += 4;
+ if (res_length == -1)
+ goto stream_failure;
+ l += res_length;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
zif = ifp->info;
assert(zif);
link_ifp = zif->link;
+ if (!link_ifp) {
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ struct interface *ifp;
+
+ ifp = if_lookup_by_index_all_vrf(zif->link_ifindex);
+ zlog_debug("macvlan parent link is not found. Parent index %d ifp %s",
+ zif->link_ifindex, ifp ? ifp->name : " ");
+ }
+ return;
+ }
link_zif = link_ifp->info;
assert(link_zif);
s = msg;
STREAM_GETC(s, advertise);
- vni = stream_get3(s);
+ STREAM_GET(&vni, s, 3);
zvni = zvni_lookup(vni);
if (!zvni)
* 2. the XG entry is used by pimd to setup the
* vxlan-termination-mroute
*/
- if (sg->src.s_addr) {
+ if (sg->src.s_addr != INADDR_ANY) {
memset(&sip, 0, sizeof(sip));
parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp);
if (!parent)
/* On SG entry deletion remove the reference to its parent XG
* entry
*/
- if (vxlan_sg->sg.src.s_addr) {
+ if (vxlan_sg->sg.src.s_addr != INADDR_ANY) {
memset(&sip, 0, sizeof(sip));
zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
}
{
struct zebra_vrf *zvrf;
- if (!local_vtep_ip.s_addr || !mcast_grp.s_addr)
+ if (local_vtep_ip.s_addr == INADDR_ANY
+ || mcast_grp.s_addr == INADDR_ANY)
return;
zvrf = vrf_info_lookup(VRF_DEFAULT);
{
struct zebra_vrf *zvrf;
- if (!local_vtep_ip.s_addr || !mcast_grp.s_addr)
+ if (local_vtep_ip.s_addr == INADDR_ANY
+ || mcast_grp.s_addr == INADDR_ANY)
return;
zvrf = vrf_info_lookup(VRF_DEFAULT);