@@ -25,6 +25,7 @@ import (
2525 "github.com/osrg/gobgp/v4/api"
2626 "github.com/osrg/gobgp/v4/pkg/packet/bgp"
2727 "github.com/stretchr/testify/assert"
28+ "github.com/stretchr/testify/require"
2829)
2930
3031func Test_OriginAttribute (t * testing.T ) {
@@ -1563,6 +1564,118 @@ func TestFullCyclePrefixSID(t *testing.T) {
15631564 }
15641565}
15651566
1567+ func TestUnmarshalSRSegments_NilFlags (t * testing.T ) {
1568+ // Flags is an optional protobuf sub-message. A caller that builds
1569+ // api.SegmentTypeA or api.SegmentTypeB without setting Flags must
1570+ // not cause a nil pointer dereference; the result should be all-zero
1571+ // flag bits.
1572+ t .Run ("SegmentTypeA_nil_flags" , func (t * testing.T ) {
1573+ segs := []* api.TunnelEncapSubTLVSRSegmentList_Segment {
1574+ {Segment : & api.TunnelEncapSubTLVSRSegmentList_Segment_A {
1575+ A : & api.SegmentTypeA {Label : 100 },
1576+ // Flags intentionally omitted (nil)
1577+ }},
1578+ }
1579+ result , err := UnmarshalSRSegments (segs )
1580+ assert .NoError (t , err )
1581+ require .Len (t , result , 1 )
1582+ seg , ok := result [0 ].(* bgp.SegmentTypeA )
1583+ require .True (t , ok )
1584+ assert .Equal (t , uint32 (100 ), seg .Label )
1585+ assert .Equal (t , uint8 (0 ), seg .Flags )
1586+ })
1587+
1588+ t .Run ("SegmentTypeB_nil_flags" , func (t * testing.T ) {
1589+ sid := []byte {0x20 , 0x01 , 0x0d , 0xb8 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x01 }
1590+ segs := []* api.TunnelEncapSubTLVSRSegmentList_Segment {
1591+ {Segment : & api.TunnelEncapSubTLVSRSegmentList_Segment_B {
1592+ B : & api.SegmentTypeB {Sid : sid },
1593+ // Flags intentionally omitted (nil)
1594+ }},
1595+ }
1596+ result , err := UnmarshalSRSegments (segs )
1597+ assert .NoError (t , err )
1598+ require .Len (t , result , 1 )
1599+ seg , ok := result [0 ].(* bgp.SegmentTypeB )
1600+ require .True (t , ok )
1601+ assert .Equal (t , sid , seg .SID )
1602+ assert .Equal (t , uint8 (0 ), seg .Flags )
1603+ })
1604+ }
1605+
1606+ func TestUnmarshalSRSegments_RoundTrip (t * testing.T ) {
1607+ t .Run ("SegmentTypeA" , func (t * testing.T ) {
1608+ orig := []bgp.TunnelEncapSubTLVInterface {
1609+ & bgp.SegmentTypeA {
1610+ TunnelEncapSubTLV : bgp.TunnelEncapSubTLV {Type : bgp .EncapSubTLVType (bgp .TypeA ), Length : 6 },
1611+ Label : 200 ,
1612+ Flags : 0x80 | 0x10 , // VFlag + BFlag
1613+ },
1614+ }
1615+ marshaled , err := MarshalSRSegments (orig )
1616+ require .NoError (t , err )
1617+ result , err := UnmarshalSRSegments (marshaled )
1618+ require .NoError (t , err )
1619+ require .Len (t , result , 1 )
1620+ seg , ok := result [0 ].(* bgp.SegmentTypeA )
1621+ require .True (t , ok )
1622+ assert .Equal (t , uint32 (200 ), seg .Label )
1623+ assert .Equal (t , uint8 (0x80 | 0x10 ), seg .Flags )
1624+ })
1625+
1626+ t .Run ("SegmentTypeB" , func (t * testing.T ) {
1627+ sid := []byte {0x20 , 0x01 , 0x0d , 0xb8 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x01 }
1628+ orig := []bgp.TunnelEncapSubTLVInterface {
1629+ & bgp.SegmentTypeB {
1630+ TunnelEncapSubTLV : bgp.TunnelEncapSubTLV {Type : bgp .EncapSubTLVType (bgp .TypeB ), Length : 18 },
1631+ SID : sid ,
1632+ Flags : 0x40 | 0x20 , // AFlag + SFlag
1633+ },
1634+ }
1635+ marshaled , err := MarshalSRSegments (orig )
1636+ require .NoError (t , err )
1637+ result , err := UnmarshalSRSegments (marshaled )
1638+ require .NoError (t , err )
1639+ require .Len (t , result , 1 )
1640+ seg , ok := result [0 ].(* bgp.SegmentTypeB )
1641+ require .True (t , ok )
1642+ assert .Equal (t , sid , seg .SID )
1643+ assert .Equal (t , uint8 (0x40 | 0x20 ), seg .Flags )
1644+ })
1645+
1646+ t .Run ("SegmentTypeB_with_SRv6EBS" , func (t * testing.T ) {
1647+ sid := []byte {0x20 , 0x01 , 0x0d , 0xb8 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x02 }
1648+ orig := []bgp.TunnelEncapSubTLVInterface {
1649+ & bgp.SegmentTypeB {
1650+ TunnelEncapSubTLV : bgp.TunnelEncapSubTLV {Type : bgp .EncapSubTLVType (bgp .TypeB ), Length : 18 },
1651+ SID : sid ,
1652+ Flags : 0x80 ,
1653+ SRv6EBS : & bgp.SRv6EndpointBehaviorStructure {
1654+ Behavior : bgp .END ,
1655+ BlockLen : 40 ,
1656+ NodeLen : 24 ,
1657+ FuncLen : 16 ,
1658+ ArgLen : 0 ,
1659+ },
1660+ },
1661+ }
1662+ marshaled , err := MarshalSRSegments (orig )
1663+ require .NoError (t , err )
1664+ result , err := UnmarshalSRSegments (marshaled )
1665+ require .NoError (t , err )
1666+ require .Len (t , result , 1 )
1667+ seg , ok := result [0 ].(* bgp.SegmentTypeB )
1668+ require .True (t , ok )
1669+ assert .Equal (t , sid , seg .SID )
1670+ assert .Equal (t , uint8 (0x80 ), seg .Flags )
1671+ require .NotNil (t , seg .SRv6EBS )
1672+ assert .Equal (t , bgp .END , seg .SRv6EBS .Behavior )
1673+ assert .Equal (t , uint8 (40 ), seg .SRv6EBS .BlockLen )
1674+ assert .Equal (t , uint8 (24 ), seg .SRv6EBS .NodeLen )
1675+ assert .Equal (t , uint8 (16 ), seg .SRv6EBS .FuncLen )
1676+ })
1677+ }
1678+
15661679func TestFullCycleSRv6SIDStructureSubSubTLV (t * testing.T ) {
15671680 tests := []struct {
15681681 name string
0 commit comments