diff options
author | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-09-02 16:14:29 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-09-04 14:22:50 +0900 |
commit | 7956ff2c70987cb5580afc8cc47c6be731fd9f0a (patch) | |
tree | ec981aef8528762fb8d2d7859d1d576e0298e5e7 /zebra/zapi.go | |
parent | f9fe9a4b9b82bc68107de381259a62fcec653364 (diff) |
zebra: add NEXTHOP_LOOKUP and IMPORT_LOOKUP
Signed-off-by: Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp>
Diffstat (limited to 'zebra/zapi.go')
-rw-r--r-- | zebra/zapi.go | 244 |
1 files changed, 231 insertions, 13 deletions
diff --git a/zebra/zapi.go b/zebra/zapi.go index 08fcf80d..d3e6abf0 100644 --- a/zebra/zapi.go +++ b/zebra/zapi.go @@ -327,6 +327,21 @@ func (c *Client) SendRedistribute() error { return nil } +func (c *Client) SendRedistributeDelete(t ROUTE_TYPE) error { + + if t < ROUTE_MAX { + body := &RedistributeBody{ + Redist: t, + } + if e := c.SendCommand(REDISTRIBUTE_DELETE, body); e != nil { + return e + } + } else { + fmt.Errorf("unknown route type: %d", t) + } + return nil +} + func (c *Client) Close() error { close(c.outgoing) return c.conn.Close() @@ -585,9 +600,9 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte) error { byteLen := int((b.PrefixLength + 7) / 8) - curPos := 4 + pos := 4 buf := make([]byte, addrLen) - copy(buf, data[curPos:curPos+byteLen]) + copy(buf, data[pos:pos+byteLen]) if isV4 { b.Prefix = net.IP(buf).To4() @@ -595,12 +610,12 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte) error { b.Prefix = net.IP(buf).To16() } - curPos += byteLen + pos += byteLen rest := 0 var numNexthop int if b.Message&MESSAGE_NEXTHOP > 0 { - numNexthop = int(data[curPos]) + numNexthop = int(data[pos]) // rest = numNexthop(1) + (nexthop(4 or 16) + placeholder(1) + ifindex(4)) * numNexthop rest += 1 + numNexthop*(int(addrLen)+5) } @@ -615,7 +630,7 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte) error { rest += 4 } - if len(data[curPos:]) != rest { + if len(data[pos:]) != rest { return fmt.Errorf("message length invalid") } @@ -623,9 +638,9 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte) error { b.Ifindexs = []uint32{} if b.Message&MESSAGE_NEXTHOP > 0 { - curPos += 1 + pos += 1 for i := 0; i < numNexthop; i++ { - addr := data[curPos : curPos+int(addrLen)] + addr := data[pos : pos+int(addrLen)] var nexthop net.IP if isV4 { nexthop = net.IP(addr).To4() @@ -635,24 +650,221 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte) error { b.Nexthops = append(b.Nexthops, nexthop) // skip nexthop and 1byte place holder - curPos += int(addrLen + 1) - ifidx := binary.BigEndian.Uint32(data[curPos : curPos+4]) + pos += int(addrLen + 1) + ifidx := binary.BigEndian.Uint32(data[pos : pos+4]) b.Ifindexs = append(b.Ifindexs, ifidx) - curPos += 4 + pos += 4 } } if b.Message&MESSAGE_DISTANCE > 0 { - b.Distance = data[curPos] + b.Distance = data[pos] } if b.Message&MESSAGE_METRIC > 0 { - curPos += 1 - b.Metric = binary.BigEndian.Uint32(data[curPos : curPos+4]) + pos += 1 + b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) } return nil } +func (b *IPRouteBody) String() string { + s := fmt.Sprintf("type: %s, flags: %s, message: %d, prefix: %s, length: %d, nexthop: %s, ifindex: %d, distance: %d, metric: %d", + b.Type.String(), b.Flags.String(), b.Message, b.Prefix.String(), b.PrefixLength, b.Nexthops[0].String(), b.Ifindexs[0], b.Distance, b.Metric) + return s +} + +type NexthopLookupBody struct { + Api API_TYPE + Addr net.IP + Metric uint32 + Nexthops []*Nexthop +} + +type Nexthop struct { + Ifname string + Ifindex uint32 + Type NEXTHOP_FLAG + Addr net.IP +} + +func (n *Nexthop) String() string { + s := fmt.Sprintf("type: %s, addr: %s, ifindex: %d, ifname: %s", n.Type.String(), n.Addr.String(), n.Ifindex, n.Ifname) + return s +} + +func (b *NexthopLookupBody) Serialize() ([]byte, error) { + + isV4 := b.Api == IPV4_NEXTHOP_LOOKUP + buf := make([]byte, 0) + + if isV4 { + buf = append(buf, b.Addr.To4()...) + } else { + buf = append(buf, b.Addr.To16()...) + } + return buf, nil +} + +func (b *NexthopLookupBody) DecodeFromBytes(data []byte) error { + + isV4 := b.Api == IPV4_NEXTHOP_LOOKUP + var addrLen uint8 = net.IPv4len + if !isV4 { + addrLen = net.IPv6len + } + + if len(data) < int(addrLen) { + return fmt.Errorf("message length invalid") + } + + buf := make([]byte, addrLen) + copy(buf, data[0:addrLen]) + pos := addrLen + + if isV4 { + b.Addr = net.IP(buf).To4() + } else { + b.Addr = net.IP(buf).To16() + } + + if len(data[pos:]) > int(1+addrLen) { + b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + nexthopNum := int(data[pos]) + b.Nexthops = []*Nexthop{} + + if nexthopNum > 0 { + pos += 1 + for i := 0; i < nexthopNum; i++ { + nh := &Nexthop{} + nh.Type = NEXTHOP_FLAG(data[pos]) + pos += 1 + + switch nh.Type { + case NEXTHOP_IPV4, NEXTHOP_IPV6: + b := make([]byte, addrLen) + copy(b, data[pos:pos+addrLen]) + if isV4 { + nh.Addr = net.IP(b).To4() + } else { + nh.Addr = net.IP(b).To16() + } + pos += addrLen + + case NEXTHOP_IPV4_IFINDEX, NEXTHOP_IPV6_IFINDEX, NEXTHOP_IPV6_IFNAME: + b := make([]byte, addrLen) + copy(b, data[pos:pos+addrLen]) + if isV4 { + nh.Addr = net.IP(b).To4() + } else { + nh.Addr = net.IP(b).To16() + } + pos += addrLen + nh.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + + case NEXTHOP_IFINDEX, NEXTHOP_IFNAME: + nh.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + } + b.Nexthops = append(b.Nexthops, nh) + } + } + } + + return nil +} + +func (b *NexthopLookupBody) String() string { + s := fmt.Sprintf("addr: %s, metric: %d", b.Addr, b.Metric) + if len(b.Nexthops) > 0 { + for _, nh := range b.Nexthops { + s = s + fmt.Sprintf(", nexthop:{%s}", nh.String()) + } + } + return s +} + +type ImportLookupBody struct { + Api API_TYPE + PrefixLength uint8 + Prefix net.IP + Addr net.IP + Metric uint32 + Nexthops []*Nexthop +} + +func (b *ImportLookupBody) Serialize() ([]byte, error) { + buf := make([]byte, 1) + buf[0] = b.PrefixLength + buf = append(buf, b.Addr.To4()...) + return buf, nil +} + +func (b *ImportLookupBody) DecodeFromBytes(data []byte) error { + + var addrLen uint8 = net.IPv4len + + if len(data) < int(addrLen) { + return fmt.Errorf("message length invalid") + } + + buf := make([]byte, addrLen) + copy(buf, data[0:addrLen]) + pos := addrLen + + b.Addr = net.IP(buf).To4() + + if len(data[pos:]) > int(1+addrLen) { + b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + nexthopNum := int(data[pos]) + b.Nexthops = []*Nexthop{} + if nexthopNum > 0 { + pos += 1 + for i := 0; i < nexthopNum; i++ { + nh := &Nexthop{} + nh.Type = NEXTHOP_FLAG(data[pos]) + pos += 1 + + switch nh.Type { + case NEXTHOP_IPV4: + b := make([]byte, addrLen) + copy(b, data[pos:pos+addrLen]) + nh.Addr = net.IP(b).To4() + pos += addrLen + + case NEXTHOP_IPV4_IFINDEX: + b := make([]byte, addrLen) + copy(b, data[pos:pos+addrLen]) + nh.Addr = net.IP(b).To4() + pos += addrLen + nh.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + + case NEXTHOP_IFINDEX, NEXTHOP_IFNAME: + nh.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + } + b.Nexthops = append(b.Nexthops, nh) + } + } + } + + return nil +} + +func (b *ImportLookupBody) String() string { + s := fmt.Sprintf("addr: %s, metric: %d", b.Addr, b.Metric) + if len(b.Nexthops) > 0 { + for _, nh := range b.Nexthops { + s = s + fmt.Sprintf(", nexthop:{%s}", nh.String()) + } + } + return s +} + type Message struct { Header Header Body Body @@ -688,6 +900,12 @@ func ParseMessage(hdr *Header, data []byte) (*Message, error) { case IPV4_ROUTE_ADD, IPV6_ROUTE_ADD, IPV4_ROUTE_DELETE, IPV6_ROUTE_DELETE: m.Body = &IPRouteBody{Api: m.Header.Command} log.Debugf("ipv4/v6 route add/delete message received: %v", data) + case IPV4_NEXTHOP_LOOKUP, IPV6_NEXTHOP_LOOKUP: + m.Body = &NexthopLookupBody{Api: m.Header.Command} + log.Debugf("ipv4/v6 nexthop lookup received: %v", data) + case IPV4_IMPORT_LOOKUP: + m.Body = &ImportLookupBody{Api: m.Header.Command} + log.Debugf("ipv4 import lookup message received: %v", data) default: return nil, fmt.Errorf("Unknown zapi command: %d", m.Header.Command) } |