# Table of Contents

- [what is neutron-ipv6-bgp-injector](what-is-neutron-ipv6-injector)
  * [General description](#general-description)
- [How to setup](#how-to-setup)
  * [Installing](#installing)
  * [How to configure](#how-to-configure)
- [Code description](code-description)

# What is neutron-ipv6-bgp-injector

### General description

This package provides a daemon that advertize each individual IPv6 addresses
to a BGP peer, so that the router knows what list of IP we are using in a
deployment. This may be useful as neutron-dynamic-routing can only advertize
for /64 blocks, and in some case (like during a migration), it may be
desirable to have more fine-grained advertizing.

This is also useful if one wants to route only the IPv6 addresses actually
used in a deployment, blocking the traffic of non-reachable IPv6 before it
reaches the cloud, making the deployment DoS-by-IPv6-scan-proof.

# How to setup

## Installing

Simply install the package:
```
apt-get install neutron-ipv6-bgp-injector
```

Note that neutron-ipv6-bgp-injector can only work with
neutron-dynamic-routing, as it fetches the list of advertized IPv6 subnet
through a bgp-speaker.

## How to configure

The package comes with a configuration file:

/etc/neutron-ipv6-bgp-injector/neutron-ipv6-bgp-injector.conf

Minimal values to configure in the [DEFAULT] section:
- subnet_list List of IPv6 subnet to watch for IPv6 advertizing
- bgp_peer_ip IP address of the BGP peer to connect to
- bgp_peer_as AS number of the BGP peer to connect to
- bgp_our_router_id The router_id of neutron-ipv6-bgp-injector
- bgp_our_as The AS number of neutron-ipv6-bgp-injector
- bgp_speaker_id neutron-dynamic-routing BGP speaker ID that contains the IPv6 advertizer

Then one needs to configure the [neutron] section to access the Neutron API,
and the transport_url to connect to RabbitMQ. WARNING: transport_url must
be configured to the notification bus, not the "normal" bus, which may be
different from each other depending on your deployment.

# Code description

After loading its configuration file, nibi (neutron-ipv6-bgp-injector)
calls query_neutron_ipv6_next_hop. This function talks to Neutron API to
fetch the next HOP for all subnets defined in the subnet_list (configured
in the configuration file). Once that's done, nibi queries Neutron API
to fetch all ports that have an IP in these subnets, and list them, to
establish 3 dictionaries:

- ipv6_nexthop_list IP -> nexthop IP
- subnet_id_to_nexthop subnet_id -> nexthop IP
- list_of_ports_vs_ipv6 port_id -> ipv6

There are maintained all the time until the daemon dies.

Once that's done, nibi prepare a BGP manager object:

```
bgp_manager = BGPSpeakerManager(conf=conf)
```

and injects all the routes returned by query_neutron_ipv6_next_hop():

```
    for ip6, next_hop in ipv6_nexthop_list.items():
        bgp_manager.inject_route(prefix = ip6 + '/128', next_hop=next_hop)
```

At this point, the daemon is already advertizing all single IPv6 /128.

Then nibi connects to Rabbit, and listen for any port notification.

When a port is added, modified or removed, the PortEventEndpoint info()
method calls the relevant bgp_manager (ie: inject_route or withdraw_route)
to keep everything up-to-date.
