+ /* Dynamic */
+ if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
+ || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
+ {
+ if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV) && CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV))
+ json_object_string_add(json_cap, "dynamic", "advertisedAndReceived");
+ else if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
+ json_object_string_add(json_cap, "dynamic", "advertised");
+ else if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV))
+ json_object_string_add(json_cap, "dynamic", "received");
+ }
+
+ /* Extended nexthop */
+ if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV)
+ || CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV))
+ {
+ json_object *json_nxt = NULL;
+ const char *print_store;
+
+ json_nxt = json_object_new_object();
+
+ if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV) && CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV))
+ json_object_string_add(json_cap, "extendedNexthop", "advertisedAndReceived");
+ else if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV))
+ json_object_string_add(json_cap, "extendedNexthop", "advertised");
+ else if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV))
+ json_object_string_add(json_cap, "extendedNexthop", "received");
+
+ if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV))
+ {
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ if (CHECK_FLAG (p->af_cap[AFI_IP][safi], PEER_CAP_ENHE_AF_RCV))
+ {
+ print_store = afi_safi_print (AFI_IP, safi);
+ json_object_string_add(json_nxt, print_store, "recieved");
+ }
+ }
+ json_object_object_add(json_cap, "extendedNexthopFamililesByPeer", json_nxt);
+ }
+ }
+
+ /* Route Refresh */
+ if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV)
+ || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV)
+ || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))
+ {
+ if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV) && (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV) || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV)))
+ {
+ if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV) && CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV))
+ json_object_string_add(json_cap, "routeRefresh", "advertisedAndReceivedOldNew");
+ else
+ {
+ if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))
+ json_object_string_add(json_cap, "routeRefresh", "advertisedAndReceivedOld");
+ else
+ json_object_string_add(json_cap, "routeRefresh", "advertisedAndReceivedNew");
+ }
+ }
+ else if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV))
+ json_object_string_add(json_cap, "routeRefresh", "advertised");
+ else if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV) || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))
+ json_object_string_add(json_cap, "routeRefresh", "received");
+ }
+
+ /* Multiprotocol Extensions */
+ json_object *json_multi = NULL;
+ json_multi = json_object_new_object();
+
+ for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+ {
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ if (p->afc_adv[afi][safi] || p->afc_recv[afi][safi])
+ {
+ json_object *json_exten = NULL;
+ json_exten = json_object_new_object();
+
+ if (p->afc_adv[afi][safi] && p->afc_recv[afi][safi])
+ json_object_boolean_true_add(json_exten, "advertisedAndReceived");
+ else if (p->afc_adv[afi][safi])
+ json_object_boolean_true_add(json_exten, "advertised");
+ else if (p->afc_recv[afi][safi])
+ json_object_boolean_true_add(json_exten, "received");
+
+ json_object_object_add(json_multi, afi_safi_print (afi, safi), json_exten);
+ }
+ }
+ }
+ json_object_object_add(json_cap, "multiprotocolExtensions", json_multi);
+
+ /* Gracefull Restart */
+ if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)
+ || CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV))
+ {
+ if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV) && CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV))
+ json_object_string_add(json_cap, "gracefulRestart", "advertisedAndReceived");
+ else if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV))
+ json_object_string_add(json_cap, "gracefulRestartCapability", "advertised");
+ else if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV))
+ json_object_string_add(json_cap, "gracefulRestartCapability", "received");
+
+ if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV))
+ {
+ int restart_af_count = 0;
+ json_object *json_restart = NULL;
+ json_restart = json_object_new_object();
+
+ json_object_int_add(json_cap, "gracefulRestartRemoteTimerMsecs", p->v_gr_restart * 1000);
+
+ for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+ {
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
+ {
+ json_object *json_sub = NULL;
+ json_sub = json_object_new_object();
+
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
+ json_object_boolean_true_add(json_sub, "preserved");
+ restart_af_count++;
+ json_object_object_add(json_restart, afi_safi_print (afi, safi), json_sub);
+ }
+ }
+ }
+ if (! restart_af_count)
+ json_object_string_add(json_cap, "addressFamiliesByPeer", "none");
+ else
+ json_object_object_add(json_cap, "addressFamiliesByPeer", json_restart);
+ }
+ }
+ json_object_object_add(json_neigh, "neighborCapabilities", json_cap);
+ }
+ else
+ {
+ vty_out (vty, " Neighbor capabilities:%s", VTY_NEWLINE);
+
+ /* AS4 */
+ if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV)
+ || CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV))
+ {
+ vty_out (vty, " 4 Byte AS:");
+ if (CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV))
+ vty_out (vty, " advertised");
+ if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV))
+ vty_out (vty, " %sreceived",
+ CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV) ? "and " : "");
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+
+ /* AddPath */
+ if (CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_RCV)
+ || CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_ADV))
+ {
+ vty_out (vty, " AddPath:%s", VTY_NEWLINE);
+
+ for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)