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