github.com/osrg/gobgp/v3@v3.30.0/pkg/config/oc/default.go (about)

     1  package oc
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math"
     7  	"net"
     8  	"reflect"
     9  	"strconv"
    10  
    11  	"github.com/osrg/gobgp/v3/internal/pkg/version"
    12  	"github.com/osrg/gobgp/v3/pkg/packet/bgp"
    13  	"github.com/osrg/gobgp/v3/pkg/packet/bmp"
    14  	"github.com/osrg/gobgp/v3/pkg/packet/rtr"
    15  	"github.com/osrg/gobgp/v3/pkg/zebra"
    16  	"github.com/spf13/viper"
    17  )
    18  
    19  const (
    20  	DEFAULT_HOLDTIME                  = 90
    21  	DEFAULT_IDLE_HOLDTIME_AFTER_RESET = 30
    22  	DEFAULT_CONNECT_RETRY             = 120
    23  )
    24  
    25  var forcedOverwrittenConfig = []string{
    26  	"neighbor.config.peer-as",
    27  	"neighbor.timers.config.minimum-advertisement-interval",
    28  }
    29  
    30  var configuredFields map[string]interface{}
    31  
    32  func RegisterConfiguredFields(addr string, n interface{}) {
    33  	if configuredFields == nil {
    34  		configuredFields = make(map[string]interface{})
    35  	}
    36  	configuredFields[addr] = n
    37  }
    38  
    39  func defaultAfiSafi(typ AfiSafiType, enable bool) AfiSafi {
    40  	return AfiSafi{
    41  		Config: AfiSafiConfig{
    42  			AfiSafiName: typ,
    43  			Enabled:     enable,
    44  		},
    45  		State: AfiSafiState{
    46  			AfiSafiName: typ,
    47  			Family:      bgp.AddressFamilyValueMap[string(typ)],
    48  		},
    49  	}
    50  }
    51  
    52  func SetDefaultNeighborConfigValues(n *Neighbor, pg *PeerGroup, g *Global) error {
    53  	// Determines this function is called against the same Neighbor struct,
    54  	// and if already called, returns immediately.
    55  	if n.State.LocalAs != 0 {
    56  		return nil
    57  	}
    58  
    59  	return setDefaultNeighborConfigValuesWithViper(nil, n, g, pg)
    60  }
    61  
    62  func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Global, pg *PeerGroup) error {
    63  	if n == nil {
    64  		return fmt.Errorf("neighbor config is nil")
    65  	}
    66  	if g == nil {
    67  		return fmt.Errorf("global config is nil")
    68  	}
    69  
    70  	if v == nil {
    71  		v = viper.New()
    72  	}
    73  
    74  	if pg != nil {
    75  		if err := OverwriteNeighborConfigWithPeerGroup(n, pg); err != nil {
    76  			return err
    77  		}
    78  	}
    79  
    80  	if n.Config.LocalAs == 0 {
    81  		n.Config.LocalAs = g.Config.As
    82  		if !g.Confederation.Config.Enabled || n.IsConfederation(g) {
    83  			n.Config.LocalAs = g.Config.As
    84  		} else {
    85  			n.Config.LocalAs = g.Confederation.Config.Identifier
    86  		}
    87  	}
    88  	n.State.LocalAs = n.Config.LocalAs
    89  
    90  	if n.Config.PeerAs != n.Config.LocalAs {
    91  		n.Config.PeerType = PEER_TYPE_EXTERNAL
    92  		n.State.PeerType = PEER_TYPE_EXTERNAL
    93  		n.State.RemovePrivateAs = n.Config.RemovePrivateAs
    94  		n.AsPathOptions.State.ReplacePeerAs = n.AsPathOptions.Config.ReplacePeerAs
    95  	} else {
    96  		n.Config.PeerType = PEER_TYPE_INTERNAL
    97  		n.State.PeerType = PEER_TYPE_INTERNAL
    98  		if string(n.Config.RemovePrivateAs) != "" {
    99  			return fmt.Errorf("can't set remove-private-as for iBGP peer")
   100  		}
   101  		if n.AsPathOptions.Config.ReplacePeerAs {
   102  			return fmt.Errorf("can't set replace-peer-as for iBGP peer")
   103  		}
   104  	}
   105  
   106  	if n.State.NeighborAddress == "" {
   107  		n.State.NeighborAddress = n.Config.NeighborAddress
   108  	}
   109  
   110  	n.State.PeerAs = n.Config.PeerAs
   111  	n.AsPathOptions.State.AllowOwnAs = n.AsPathOptions.Config.AllowOwnAs
   112  
   113  	if !v.IsSet("neighbor.error-handling.config.treat-as-withdraw") {
   114  		n.ErrorHandling.Config.TreatAsWithdraw = true
   115  	}
   116  
   117  	if !v.IsSet("neighbor.timers.config.connect-retry") && n.Timers.Config.ConnectRetry == 0 {
   118  		n.Timers.Config.ConnectRetry = float64(DEFAULT_CONNECT_RETRY)
   119  	}
   120  	if !v.IsSet("neighbor.timers.config.hold-time") && n.Timers.Config.HoldTime == 0 {
   121  		n.Timers.Config.HoldTime = float64(DEFAULT_HOLDTIME)
   122  	}
   123  	if !v.IsSet("neighbor.timers.config.keepalive-interval") && n.Timers.Config.KeepaliveInterval == 0 {
   124  		n.Timers.Config.KeepaliveInterval = n.Timers.Config.HoldTime / 3
   125  	}
   126  	if !v.IsSet("neighbor.timers.config.idle-hold-time-after-reset") && n.Timers.Config.IdleHoldTimeAfterReset == 0 {
   127  		n.Timers.Config.IdleHoldTimeAfterReset = float64(DEFAULT_IDLE_HOLDTIME_AFTER_RESET)
   128  	}
   129  
   130  	if n.Config.NeighborInterface != "" {
   131  		if n.RouteServer.Config.RouteServerClient {
   132  			return fmt.Errorf("configuring route server client as unnumbered peer is not supported")
   133  		}
   134  		addr, err := GetIPv6LinkLocalNeighborAddress(n.Config.NeighborInterface)
   135  		if err != nil {
   136  			return err
   137  		}
   138  		n.State.NeighborAddress = addr
   139  	}
   140  
   141  	if n.Transport.Config.LocalAddress == "" {
   142  		if n.State.NeighborAddress == "" {
   143  			return fmt.Errorf("no neighbor address/interface specified")
   144  		}
   145  		ipAddr, err := net.ResolveIPAddr("ip", n.State.NeighborAddress)
   146  		if err != nil {
   147  			return err
   148  		}
   149  		localAddress := "0.0.0.0"
   150  		if ipAddr.IP.To4() == nil {
   151  			localAddress = "::"
   152  			if ipAddr.Zone != "" {
   153  				localAddress, err = getIPv6LinkLocalAddress(ipAddr.Zone)
   154  				if err != nil {
   155  					return err
   156  				}
   157  			}
   158  		}
   159  		n.Transport.Config.LocalAddress = localAddress
   160  	}
   161  
   162  	if len(n.AfiSafis) == 0 {
   163  		if n.Config.NeighborInterface != "" {
   164  			n.AfiSafis = []AfiSafi{
   165  				defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true),
   166  				defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true),
   167  			}
   168  		} else if ipAddr, err := net.ResolveIPAddr("ip", n.State.NeighborAddress); err != nil {
   169  			return fmt.Errorf("invalid neighbor address: %s", n.State.NeighborAddress)
   170  		} else if ipAddr.IP.To4() != nil {
   171  			n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true)}
   172  		} else {
   173  			n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true)}
   174  		}
   175  		for i := range n.AfiSafis {
   176  			n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive
   177  			n.AfiSafis[i].AddPaths.State.Receive = n.AddPaths.Config.Receive
   178  			n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax
   179  			n.AfiSafis[i].AddPaths.State.SendMax = n.AddPaths.Config.SendMax
   180  		}
   181  	} else {
   182  		afs, err := extractArray(v.Get("neighbor.afi-safis"))
   183  		if err != nil {
   184  			return err
   185  		}
   186  		for i := range n.AfiSafis {
   187  			vv := viper.New()
   188  			if len(afs) > i {
   189  				vv.Set("afi-safi", afs[i])
   190  			}
   191  			rf, err := bgp.GetRouteFamily(string(n.AfiSafis[i].Config.AfiSafiName))
   192  			if err != nil {
   193  				return err
   194  			}
   195  			n.AfiSafis[i].State.Family = rf
   196  			n.AfiSafis[i].State.AfiSafiName = n.AfiSafis[i].Config.AfiSafiName
   197  			if !vv.IsSet("afi-safi.config.enabled") {
   198  				n.AfiSafis[i].Config.Enabled = true
   199  			}
   200  			n.AfiSafis[i].MpGracefulRestart.State.Enabled = n.AfiSafis[i].MpGracefulRestart.Config.Enabled
   201  			if !vv.IsSet("afi-safi.add-paths.config.receive") {
   202  				if n.AddPaths.Config.Receive {
   203  					n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive
   204  				}
   205  			}
   206  			n.AfiSafis[i].AddPaths.State.Receive = n.AfiSafis[i].AddPaths.Config.Receive
   207  			if !vv.IsSet("afi-safi.add-paths.config.send-max") {
   208  				if n.AddPaths.Config.SendMax != 0 {
   209  					n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax
   210  				}
   211  			}
   212  			n.AfiSafis[i].AddPaths.State.SendMax = n.AfiSafis[i].AddPaths.Config.SendMax
   213  		}
   214  	}
   215  
   216  	n.State.Description = n.Config.Description
   217  	n.State.AdminDown = n.Config.AdminDown
   218  
   219  	if n.GracefulRestart.Config.Enabled {
   220  		if !v.IsSet("neighbor.graceful-restart.config.restart-time") && n.GracefulRestart.Config.RestartTime == 0 {
   221  			// RFC 4724 4. Operation
   222  			// A suggested default for the Restart Time is a value less than or
   223  			// equal to the HOLDTIME carried in the OPEN.
   224  			n.GracefulRestart.Config.RestartTime = uint16(n.Timers.Config.HoldTime)
   225  		}
   226  		if !v.IsSet("neighbor.graceful-restart.config.deferral-time") && n.GracefulRestart.Config.DeferralTime == 0 {
   227  			// RFC 4724 4.1. Procedures for the Restarting Speaker
   228  			// The value of this timer should be large
   229  			// enough, so as to provide all the peers of the Restarting Speaker with
   230  			// enough time to send all the routes to the Restarting Speaker
   231  			n.GracefulRestart.Config.DeferralTime = uint16(360)
   232  		}
   233  	}
   234  
   235  	if n.EbgpMultihop.Config.Enabled {
   236  		if n.TtlSecurity.Config.Enabled {
   237  			return fmt.Errorf("ebgp-multihop and ttl-security are mututally exclusive")
   238  		}
   239  		if n.EbgpMultihop.Config.MultihopTtl == 0 {
   240  			n.EbgpMultihop.Config.MultihopTtl = 255
   241  		}
   242  	} else if n.TtlSecurity.Config.Enabled {
   243  		if n.TtlSecurity.Config.TtlMin == 0 {
   244  			n.TtlSecurity.Config.TtlMin = 255
   245  		}
   246  	}
   247  
   248  	if n.RouteReflector.Config.RouteReflectorClient {
   249  		if n.RouteReflector.Config.RouteReflectorClusterId == "" {
   250  			n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(g.Config.RouterId)
   251  		} else {
   252  			id := string(n.RouteReflector.Config.RouteReflectorClusterId)
   253  			if ip := net.ParseIP(id).To4(); ip != nil {
   254  				n.RouteReflector.State.RouteReflectorClusterId = n.RouteReflector.Config.RouteReflectorClusterId
   255  			} else if num, err := strconv.ParseUint(id, 10, 32); err == nil {
   256  				ip = make(net.IP, 4)
   257  				binary.BigEndian.PutUint32(ip, uint32(num))
   258  				n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(ip.String())
   259  			} else {
   260  				return fmt.Errorf("route-reflector-cluster-id should be specified as IPv4 address or 32-bit unsigned integer")
   261  			}
   262  		}
   263  	}
   264  
   265  	return nil
   266  }
   267  
   268  func SetDefaultGlobalConfigValues(g *Global) error {
   269  	if len(g.AfiSafis) == 0 {
   270  		g.AfiSafis = []AfiSafi{}
   271  		for k := range AfiSafiTypeToIntMap {
   272  			g.AfiSafis = append(g.AfiSafis, defaultAfiSafi(k, true))
   273  		}
   274  	}
   275  
   276  	if g.Config.Port == 0 {
   277  		g.Config.Port = bgp.BGP_PORT
   278  	}
   279  
   280  	if len(g.Config.LocalAddressList) == 0 {
   281  		g.Config.LocalAddressList = []string{"0.0.0.0", "::"}
   282  	}
   283  	return nil
   284  }
   285  
   286  func setDefaultVrfConfigValues(v *Vrf) error {
   287  	if v == nil {
   288  		return fmt.Errorf("cannot set default values for nil vrf config")
   289  	}
   290  
   291  	if v.Config.Name == "" {
   292  		return fmt.Errorf("specify vrf name")
   293  	}
   294  
   295  	_, err := bgp.ParseRouteDistinguisher(v.Config.Rd)
   296  	if err != nil {
   297  		return fmt.Errorf("invalid rd for vrf %s: %s", v.Config.Name, v.Config.Rd)
   298  	}
   299  
   300  	if len(v.Config.ImportRtList) == 0 {
   301  		v.Config.ImportRtList = v.Config.BothRtList
   302  	}
   303  	for _, rtString := range v.Config.ImportRtList {
   304  		_, err := bgp.ParseRouteTarget(rtString)
   305  		if err != nil {
   306  			return fmt.Errorf("invalid import rt for vrf %s: %s", v.Config.Name, rtString)
   307  		}
   308  	}
   309  
   310  	if len(v.Config.ExportRtList) == 0 {
   311  		v.Config.ExportRtList = v.Config.BothRtList
   312  	}
   313  	for _, rtString := range v.Config.ExportRtList {
   314  		_, err := bgp.ParseRouteTarget(rtString)
   315  		if err != nil {
   316  			return fmt.Errorf("invalid export rt for vrf %s: %s", v.Config.Name, rtString)
   317  		}
   318  	}
   319  
   320  	return nil
   321  }
   322  
   323  func SetDefaultConfigValues(b *BgpConfigSet) error {
   324  	return setDefaultConfigValuesWithViper(nil, b)
   325  }
   326  
   327  func setDefaultPolicyConfigValuesWithViper(v *viper.Viper, p *PolicyDefinition) error {
   328  	stmts, err := extractArray(v.Get("policy.statements"))
   329  	if err != nil {
   330  		return err
   331  	}
   332  	for i := range p.Statements {
   333  		vv := viper.New()
   334  		if len(stmts) > i {
   335  			vv.Set("statement", stmts[i])
   336  		}
   337  		if !vv.IsSet("statement.actions.route-disposition") {
   338  			p.Statements[i].Actions.RouteDisposition = ROUTE_DISPOSITION_NONE
   339  		}
   340  	}
   341  	return nil
   342  }
   343  
   344  func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
   345  	if v == nil {
   346  		v = viper.New()
   347  	}
   348  
   349  	if err := SetDefaultGlobalConfigValues(&b.Global); err != nil {
   350  		return err
   351  	}
   352  
   353  	for idx, server := range b.BmpServers {
   354  		if server.Config.SysName == "" {
   355  			server.Config.SysName = "GoBGP"
   356  		}
   357  		if server.Config.SysDescr == "" {
   358  			server.Config.SysDescr = version.Version()
   359  		}
   360  		if server.Config.Port == 0 {
   361  			server.Config.Port = bmp.BMP_DEFAULT_PORT
   362  		}
   363  		if server.Config.RouteMonitoringPolicy == "" {
   364  			server.Config.RouteMonitoringPolicy = BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY
   365  		}
   366  		// statistics-timeout is uint16 value and implicitly less than 65536
   367  		if server.Config.StatisticsTimeout != 0 && server.Config.StatisticsTimeout < 15 {
   368  			return fmt.Errorf("too small statistics-timeout value: %d", server.Config.StatisticsTimeout)
   369  		}
   370  		b.BmpServers[idx] = server
   371  	}
   372  
   373  	vrfNames := make(map[string]struct{})
   374  	vrfIDs := make(map[uint32]struct{})
   375  	for idx, vrf := range b.Vrfs {
   376  		if err := setDefaultVrfConfigValues(&vrf); err != nil {
   377  			return err
   378  		}
   379  
   380  		if _, ok := vrfNames[vrf.Config.Name]; ok {
   381  			return fmt.Errorf("duplicated vrf name: %s", vrf.Config.Name)
   382  		}
   383  		vrfNames[vrf.Config.Name] = struct{}{}
   384  
   385  		if vrf.Config.Id != 0 {
   386  			if _, ok := vrfIDs[vrf.Config.Id]; ok {
   387  				return fmt.Errorf("duplicated vrf id: %d", vrf.Config.Id)
   388  			}
   389  			vrfIDs[vrf.Config.Id] = struct{}{}
   390  		}
   391  
   392  		b.Vrfs[idx] = vrf
   393  	}
   394  	// Auto assign VRF identifier
   395  	for idx, vrf := range b.Vrfs {
   396  		if vrf.Config.Id == 0 {
   397  			for id := uint32(1); id < math.MaxUint32; id++ {
   398  				if _, ok := vrfIDs[id]; !ok {
   399  					vrf.Config.Id = id
   400  					vrfIDs[id] = struct{}{}
   401  					break
   402  				}
   403  			}
   404  		}
   405  		b.Vrfs[idx] = vrf
   406  	}
   407  
   408  	if b.Zebra.Config.Url == "" {
   409  		b.Zebra.Config.Url = "unix:/var/run/quagga/zserv.api"
   410  	}
   411  	if b.Zebra.Config.Version < zebra.MinZapiVer {
   412  		b.Zebra.Config.Version = zebra.MinZapiVer
   413  	} else if b.Zebra.Config.Version > zebra.MaxZapiVer {
   414  		b.Zebra.Config.Version = zebra.MaxZapiVer
   415  	}
   416  
   417  	if !v.IsSet("zebra.config.nexthop-trigger-enable") && !b.Zebra.Config.NexthopTriggerEnable && b.Zebra.Config.Version > 2 {
   418  		b.Zebra.Config.NexthopTriggerEnable = true
   419  	}
   420  	if b.Zebra.Config.NexthopTriggerDelay == 0 {
   421  		b.Zebra.Config.NexthopTriggerDelay = 5
   422  	}
   423  
   424  	list, err := extractArray(v.Get("neighbors"))
   425  	if err != nil {
   426  		return err
   427  	}
   428  
   429  	for idx, n := range b.Neighbors {
   430  		vv := viper.New()
   431  		if len(list) > idx {
   432  			vv.Set("neighbor", list[idx])
   433  		}
   434  
   435  		pg, err := b.getPeerGroup(n.Config.PeerGroup)
   436  		if err != nil {
   437  			return nil
   438  		}
   439  
   440  		if pg != nil {
   441  			identifier := vv.Get("neighbor.config.neighbor-address")
   442  			if identifier == nil {
   443  				identifier = vv.Get("neighbor.config.neighbor-interface")
   444  			}
   445  			RegisterConfiguredFields(identifier.(string), list[idx])
   446  		}
   447  
   448  		if err := setDefaultNeighborConfigValuesWithViper(vv, &n, &b.Global, pg); err != nil {
   449  			return err
   450  		}
   451  		b.Neighbors[idx] = n
   452  	}
   453  
   454  	for _, d := range b.DynamicNeighbors {
   455  		if err := d.validate(b); err != nil {
   456  			return err
   457  		}
   458  	}
   459  
   460  	for idx, r := range b.RpkiServers {
   461  		if r.Config.Port == 0 {
   462  			b.RpkiServers[idx].Config.Port = rtr.RPKI_DEFAULT_PORT
   463  		}
   464  	}
   465  
   466  	list, err = extractArray(v.Get("policy-definitions"))
   467  	if err != nil {
   468  		return err
   469  	}
   470  
   471  	for idx, p := range b.PolicyDefinitions {
   472  		vv := viper.New()
   473  		if len(list) > idx {
   474  			vv.Set("policy", list[idx])
   475  		}
   476  		if err := setDefaultPolicyConfigValuesWithViper(vv, &p); err != nil {
   477  			return err
   478  		}
   479  		b.PolicyDefinitions[idx] = p
   480  	}
   481  
   482  	return nil
   483  }
   484  
   485  func OverwriteNeighborConfigWithPeerGroup(c *Neighbor, pg *PeerGroup) error {
   486  	v := viper.New()
   487  
   488  	val, ok := configuredFields[c.Config.NeighborAddress]
   489  	if ok {
   490  		v.Set("neighbor", val)
   491  	} else {
   492  		v.Set("neighbor.config.peer-group", c.Config.PeerGroup)
   493  	}
   494  
   495  	overwriteConfig(&c.Config, &pg.Config, "neighbor.config", v)
   496  	overwriteConfig(&c.Timers.Config, &pg.Timers.Config, "neighbor.timers.config", v)
   497  	overwriteConfig(&c.Transport.Config, &pg.Transport.Config, "neighbor.transport.config", v)
   498  	overwriteConfig(&c.ErrorHandling.Config, &pg.ErrorHandling.Config, "neighbor.error-handling.config", v)
   499  	overwriteConfig(&c.LoggingOptions.Config, &pg.LoggingOptions.Config, "neighbor.logging-options.config", v)
   500  	overwriteConfig(&c.EbgpMultihop.Config, &pg.EbgpMultihop.Config, "neighbor.ebgp-multihop.config", v)
   501  	overwriteConfig(&c.RouteReflector.Config, &pg.RouteReflector.Config, "neighbor.route-reflector.config", v)
   502  	overwriteConfig(&c.AsPathOptions.Config, &pg.AsPathOptions.Config, "neighbor.as-path-options.config", v)
   503  	overwriteConfig(&c.AddPaths.Config, &pg.AddPaths.Config, "neighbor.add-paths.config", v)
   504  	overwriteConfig(&c.GracefulRestart.Config, &pg.GracefulRestart.Config, "neighbor.gradeful-restart.config", v)
   505  	overwriteConfig(&c.ApplyPolicy.Config, &pg.ApplyPolicy.Config, "neighbor.apply-policy.config", v)
   506  	overwriteConfig(&c.UseMultiplePaths.Config, &pg.UseMultiplePaths.Config, "neighbor.use-multiple-paths.config", v)
   507  	overwriteConfig(&c.RouteServer.Config, &pg.RouteServer.Config, "neighbor.route-server.config", v)
   508  	overwriteConfig(&c.TtlSecurity.Config, &pg.TtlSecurity.Config, "neighbor.ttl-security.config", v)
   509  
   510  	if !v.IsSet("neighbor.afi-safis") {
   511  		c.AfiSafis = append([]AfiSafi{}, pg.AfiSafis...)
   512  	}
   513  
   514  	return nil
   515  }
   516  
   517  func overwriteConfig(c, pg interface{}, tagPrefix string, v *viper.Viper) {
   518  	nValue := reflect.Indirect(reflect.ValueOf(c))
   519  	nType := reflect.Indirect(nValue).Type()
   520  	pgValue := reflect.Indirect(reflect.ValueOf(pg))
   521  	pgType := reflect.Indirect(pgValue).Type()
   522  
   523  	for i := 0; i < pgType.NumField(); i++ {
   524  		field := pgType.Field(i).Name
   525  		tag := tagPrefix + "." + nType.Field(i).Tag.Get("mapstructure")
   526  		if func() bool {
   527  			for _, t := range forcedOverwrittenConfig {
   528  				if t == tag {
   529  					return true
   530  				}
   531  			}
   532  			return false
   533  		}() || !v.IsSet(tag) {
   534  			nValue.FieldByName(field).Set(pgValue.FieldByName(field))
   535  		}
   536  	}
   537  }