@@ -514,6 +514,143 @@ int rtnl_nh_set_id(struct rtnl_nh *nh, uint32_t id)
514514 return 0 ;
515515}
516516
517+ /* ------------------------------------------------------------------------- */
518+ /* Message construction & kernel interaction */
519+ /* ------------------------------------------------------------------------- */
520+
521+ /* Build a netlink message representing the supplied nexthop object. */
522+ static int rtnl_nh_build_msg (struct nl_msg * msg , struct rtnl_nh * nh )
523+ {
524+ struct nhmsg hdr = {
525+ .nh_family = nh -> nh_family ,
526+ .nh_protocol = 0 , /* kernel will fill in */
527+ .nh_flags = nh -> nh_flags ,
528+ };
529+
530+ if (nlmsg_append (msg , & hdr , sizeof (hdr ), NLMSG_ALIGNTO ) < 0 )
531+ return - NLE_MSGSIZE ;
532+
533+ /* Optional attributes */
534+ if (nh -> ce_mask & NH_ATTR_ID )
535+ NLA_PUT_U32 (msg , NHA_ID , nh -> nh_id );
536+
537+ if (nh -> ce_mask & NH_ATTR_OIF )
538+ NLA_PUT_U32 (msg , NHA_OIF , nh -> nh_oif );
539+
540+ if (nh -> ce_mask & NH_ATTR_GATEWAY ) {
541+ if (!nh -> nh_gateway )
542+ return - NLE_INVAL ;
543+ NLA_PUT_ADDR (msg , NHA_GATEWAY , nh -> nh_gateway );
544+ }
545+
546+ if (nh -> ce_mask & NH_ATTR_FLAG_BLACKHOLE )
547+ NLA_PUT_FLAG (msg , NHA_BLACKHOLE );
548+
549+ /* Nexthop group */
550+ if (nh -> ce_mask & NH_ATTR_GROUP ) {
551+ struct nexthop_grp * grp ;
552+ struct nlattr * attr ;
553+ unsigned int sz ;
554+
555+ if (!nh -> nh_group || nh -> nh_group -> size == 0 )
556+ return - NLE_INVAL ;
557+
558+ sz = nh -> nh_group -> size * sizeof (struct nexthop_grp );
559+ attr = nla_reserve (msg , NHA_GROUP , sz );
560+ if (!attr )
561+ goto nla_put_failure ;
562+
563+ grp = nla_data (attr );
564+ for (unsigned int i = 0 ; i < nh -> nh_group -> size ; i ++ ) {
565+ grp [i ].id = nh -> nh_group -> entries [i ].nh_id ;
566+ grp [i ].weight = nh -> nh_group -> entries [i ].weight ;
567+ grp [i ].resvd1 = 0 ;
568+ grp [i ].resvd2 = 0 ;
569+ }
570+
571+ /* Optional group type */
572+ if (nh -> nh_group_type )
573+ NLA_PUT_U16 (msg , NHA_GROUP_TYPE , nh -> nh_group_type );
574+
575+ /* If the group type is resilient and the caller supplied additional
576+ * resilient parameters (bucket size, timers, ...), add them as a
577+ * nested NHA_RES_GROUP attribute. Only pass through the parameters
578+ * that were explicitly set on the nexthop object.
579+ */
580+ if (nh -> nh_group_type == NEXTHOP_GRP_TYPE_RES &&
581+ (nh -> ce_mask &
582+ (NH_ATTR_RES_BUCKETS | NH_ATTR_RES_IDLE_TIMER |
583+ NH_ATTR_RES_UNBALANCED_TIMER ))) {
584+ struct nlattr * res_grp ;
585+
586+ res_grp = nla_nest_start (msg , NHA_RES_GROUP );
587+ if (!res_grp )
588+ goto nla_put_failure ;
589+
590+ if (nh -> ce_mask & NH_ATTR_RES_BUCKETS )
591+ NLA_PUT_U16 (msg , NHA_RES_GROUP_BUCKETS ,
592+ nh -> res_grp_buckets );
593+
594+ if (nh -> ce_mask & NH_ATTR_RES_IDLE_TIMER )
595+ NLA_PUT_U32 (msg , NHA_RES_GROUP_IDLE_TIMER ,
596+ nh -> res_grp_idle_timer );
597+
598+ if (nh -> ce_mask & NH_ATTR_RES_UNBALANCED_TIMER )
599+ NLA_PUT_U32 (msg , NHA_RES_GROUP_UNBALANCED_TIMER ,
600+ nh -> res_grp_unbalanced_timer );
601+
602+ nla_nest_end (msg , res_grp );
603+ }
604+ }
605+
606+ return 0 ;
607+
608+ nla_put_failure :
609+ return - NLE_MSGSIZE ;
610+ }
611+
612+ /* Helper to build generic nexthop request messages */
613+ static int build_nh_msg (struct rtnl_nh * tmpl , int cmd , int flags ,
614+ struct nl_msg * * result )
615+ {
616+ _nl_auto_nl_msg struct nl_msg * msg = NULL ;
617+ int err ;
618+
619+ msg = nlmsg_alloc_simple (cmd , flags );
620+ if (!msg )
621+ return - NLE_NOMEM ;
622+
623+ err = rtnl_nh_build_msg (msg , tmpl );
624+ if (err < 0 ) {
625+ return err ;
626+ }
627+
628+ * result = _nl_steal_pointer (& msg );
629+ return 0 ;
630+ }
631+
632+ static int rtnl_nh_build_add_request (struct rtnl_nh * tmpl , int flags ,
633+ struct nl_msg * * result )
634+ {
635+ return build_nh_msg (tmpl , RTM_NEWNEXTHOP , NLM_F_CREATE | flags , result );
636+ }
637+
638+ int rtnl_nh_add (struct nl_sock * sk , struct rtnl_nh * nh , int flags )
639+ {
640+ _nl_auto_nl_msg struct nl_msg * msg = NULL ;
641+ int err ;
642+
643+ err = rtnl_nh_build_add_request (nh , flags , & msg );
644+ if (err < 0 )
645+ return err ;
646+
647+ err = nl_send_auto_complete (sk , msg );
648+ if (err < 0 )
649+ return err ;
650+
651+ return wait_for_ack (sk );
652+ }
653+
517654static struct nla_policy nh_res_group_policy [NHA_RES_GROUP_MAX + 1 ] = {
518655 [NHA_RES_GROUP_UNSPEC ] = { .type = NLA_UNSPEC },
519656 [NHA_RES_GROUP_BUCKETS ] = { .type = NLA_U16 },
0 commit comments