diff --git a/protocols/bgp/packet/fuzzing.go b/protocols/bgp/packet/fuzzing.go
index 0adaded071d6eb2f23ecd4eb92055daa266cd8bb..9f829cc89c3dcfb7566287fa9c6c3ffbab11ce5b 100644
--- a/protocols/bgp/packet/fuzzing.go
+++ b/protocols/bgp/packet/fuzzing.go
@@ -35,13 +35,16 @@ func getAllOptions() []types.Options {
 	parameters := []bool{true, false}
 	var ret []types.Options
 	for _, octet := range parameters {
-		for _, multi := range parameters {
-			for _, addPathX := range parameters {
-				ret = append(ret, types.Options{
-					Supports4OctetASN:     octet,
-					SupportsMultiProtocol: multi,
-					AddPathRX:             addPathX,
-				})
+		for _, mpbgp4 := range parameters {
+			for _, mpbgp6 := range parameters {
+				for _, addPathX := range parameters {
+					ret = append(ret, types.Options{
+						Supports4OctetASN: octet,
+						MultiProtocolIPv4: mpbgp4,
+						MultiProtocolIPv6: mpbgp6,
+						AddPathRX:         addPathX,
+					})
+				}
 			}
 		}
 	}
diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go
index 1e614ab1a45315f7ba13df63a18531c5937a92e8..60eb417202135a54f1488f0fd10af620c997b2ec 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -72,23 +72,23 @@ type FSM struct {
 	connectionCancelFunc context.CancelFunc
 }
 
-// NewPassiveFSM2 initiates a new passive FSM
-func NewPassiveFSM2(peer *peer, con *net.TCPConn) *FSM {
-	fsm := newFSM2(peer)
+// NewPassiveFSM initiates a new passive FSM
+func NewPassiveFSM(peer *peer, con *net.TCPConn) *FSM {
+	fsm := newFSM(peer)
 	fsm.con = con
 	fsm.state = newIdleState(fsm)
 	return fsm
 }
 
-// NewActiveFSM2 initiates a new passive FSM
-func NewActiveFSM2(peer *peer) *FSM {
-	fsm := newFSM2(peer)
+// NewActiveFSM initiates a new passive FSM
+func NewActiveFSM(peer *peer) *FSM {
+	fsm := newFSM(peer)
 	fsm.active = true
 	fsm.state = newIdleState(fsm)
 	return fsm
 }
 
-func newFSM2(peer *peer) *FSM {
+func newFSM(peer *peer) *FSM {
 	f := &FSM{
 		connectRetryTime: time.Minute,
 		peer:             peer,
diff --git a/protocols/bgp/server/fsm_address_family.go b/protocols/bgp/server/fsm_address_family.go
index daa5465e16f2bb90e0da43316b4bb475021ffd1b..f81f4d82905f3aeb9f60157cb2cad611859b18ec 100644
--- a/protocols/bgp/server/fsm_address_family.go
+++ b/protocols/bgp/server/fsm_address_family.go
@@ -83,14 +83,29 @@ func (f *fsmAddressFamily) dispose() {
 }
 
 func (f *fsmAddressFamily) processUpdate(u *packet.BGPUpdate) {
-	if f.afi == packet.IPv4AFI && f.safi == packet.UnicastSAFI {
-		f.withdraws(u)
-		f.updates(u)
+	if f.safi != packet.UnicastSAFI {
+		return
+	}
+
+	mp := false
+	switch f.afi {
+	case packet.IPv4AFI:
+		if f.fsm.options.MultiProtocolIPv4 {
+			mp = true
+		}
+	case packet.IPv6AFI:
+		if f.fsm.options.MultiProtocolIPv6 {
+			mp = true
+		}
 	}
 
-	if f.fsm.options.SupportsMultiProtocol {
+	if mp {
 		f.multiProtocolUpdates(u)
+		return
 	}
+
+	f.withdraws(u)
+	f.updates(u)
 }
 
 func (f *fsmAddressFamily) withdraws(u *packet.BGPUpdate) {
@@ -112,10 +127,6 @@ func (f *fsmAddressFamily) updates(u *packet.BGPUpdate) {
 }
 
 func (f *fsmAddressFamily) multiProtocolUpdates(u *packet.BGPUpdate) {
-	if !f.fsm.options.SupportsMultiProtocol {
-		return
-	}
-
 	path := f.newRoutePath()
 	f.processAttributes(u.PathAttributes, path)
 
@@ -140,6 +151,10 @@ func (f *fsmAddressFamily) newRoutePath() *route.Path {
 }
 
 func (f *fsmAddressFamily) multiProtocolUpdate(path *route.Path, nlri packet.MultiProtocolReachNLRI) {
+	if f.afi != nlri.AFI || f.safi != nlri.SAFI {
+		return
+	}
+
 	path.BGPPath.NextHop = nlri.NextHop
 
 	for _, pfx := range nlri.Prefixes {
@@ -148,6 +163,10 @@ func (f *fsmAddressFamily) multiProtocolUpdate(path *route.Path, nlri packet.Mul
 }
 
 func (f *fsmAddressFamily) multiProtocolWithdraw(path *route.Path, nlri packet.MultiProtocolUnreachNLRI) {
+	if f.afi != nlri.AFI || f.safi != nlri.SAFI {
+		return
+	}
+
 	for _, pfx := range nlri.Prefixes {
 		f.adjRIBIn.RemovePath(pfx, path)
 	}
diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index 2ffa19415e0d1233b5718b9127b8dbbfaaf9874b..246c7cbf6a9df6018c33fe135b2eae2fcf2e2ae2 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -187,7 +187,16 @@ func (s *establishedState) update(msg *packet.BGPMessage) (state, string) {
 	}
 
 	u := msg.Body.(*packet.BGPUpdate)
-	afi, safi := s.addressFamilyForUpdate(u)
+
+	if s.fsm.ipv4Unicast != nil {
+		s.fsm.ipv4Unicast.processUpdate(u)
+	}
+
+	if s.fsm.ipv6Unicast != nil {
+		s.fsm.ipv6Unicast.processUpdate(u)
+	}
+
+	afi, safi := s.updateAddressFamily(u)
 
 	if safi != packet.UnicastSAFI {
 		// only unicast support, so other SAFIs are ignored
@@ -199,19 +208,19 @@ func (s *establishedState) update(msg *packet.BGPMessage) (state, string) {
 		if s.fsm.ipv4Unicast == nil {
 			log.Warnf("Received update for family IPv4 unicast, but this family is not configured.")
 		}
-		s.fsm.ipv4Unicast.processUpdate(u)
+
 	case packet.IPv6AFI:
 		if s.fsm.ipv6Unicast == nil {
 			log.Warnf("Received update for family IPv6 unicast, but this family is not configured.")
 		}
-		s.fsm.ipv6Unicast.processUpdate(u)
+
 	}
 
 	return newEstablishedState(s.fsm), s.fsm.reason
 }
 
-func (s *establishedState) addressFamilyForUpdate(u *packet.BGPUpdate) (afi uint16, safi uint8) {
-	if !s.fsm.options.SupportsMultiProtocol || u.NLRI != nil || u.WithdrawnRoutes != nil {
+func (s *establishedState) updateAddressFamily(u *packet.BGPUpdate) (afi uint16, safi uint8) {
+	if u.WithdrawnRoutes != nil || u.NLRI != nil {
 		return packet.IPv4AFI, packet.UnicastSAFI
 	}
 
diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go
index 3ece04475f645340a60e814e3452110ce56ab5ff..be9be952ff27b615f0d24f1ec8920198a1b813be 100644
--- a/protocols/bgp/server/fsm_open_sent.go
+++ b/protocols/bgp/server/fsm_open_sent.go
@@ -175,7 +175,16 @@ func (s *openSentState) processCapability(cap packet.Capability) {
 }
 
 func (s *openSentState) processMultiProtocolCapability(cap packet.MultiProtocolCapability) {
-	s.fsm.options.SupportsMultiProtocol = true
+	if cap.SAFI != 0 {
+		return
+	}
+
+	switch cap.AFI {
+	case packet.IPv4AFI:
+		s.fsm.options.MultiProtocolIPv4 = true
+	case packet.IPv6AFI:
+		s.fsm.options.MultiProtocolIPv6 = true
+	}
 }
 
 func (s *openSentState) processAddPathCapability(addPathCap packet.AddPathCapability) {
diff --git a/protocols/bgp/server/fsm_open_sent_test.go b/protocols/bgp/server/fsm_open_sent_test.go
index fe34eede357c762de2674701132ddfa91bf170b9..03133879f5569c623a13f9f1fee49a3dcf11da59 100644
--- a/protocols/bgp/server/fsm_open_sent_test.go
+++ b/protocols/bgp/server/fsm_open_sent_test.go
@@ -66,7 +66,7 @@ func TestOpenMsgReceived(t *testing.T) {
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			fsm := newFSM2(&peer{
+			fsm := newFSM(&peer{
 				peerASN: test.asn,
 			})
 			fsm.con = &btesting.MockConn{}
diff --git a/protocols/bgp/server/fsm_test.go b/protocols/bgp/server/fsm_test.go
index 50181d8e3aa66ec34dbc21e7c18827e1b6b3d4c8..7d040713aa74d362caae10888c5c2c2b6de3bd63 100644
--- a/protocols/bgp/server/fsm_test.go
+++ b/protocols/bgp/server/fsm_test.go
@@ -13,9 +13,9 @@ import (
 	bnet "github.com/bio-routing/bio-rd/net"
 )
 
-// TestFSM255UpdatesIPv4 emulates receiving 255 BGP updates and withdraws. Checks route counts.
+// TestFSM55UpdatesIPv4 emulates receiving 255 BGP updates and withdraws. Checks route counts.
 func TestFSM100UpdatesIPv4(t *testing.T) {
-	fsmA := newFSM2(&peer{
+	fsmA := newFSM(&peer{
 		addr:     bnet.IPv4FromOctets(169, 254, 100, 100),
 		routerID: bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(),
 		ipv4: &familyParameters{
@@ -129,7 +129,7 @@ func TestFSM100UpdatesIPv4(t *testing.T) {
 
 // TestFSM255UpdatesIPv6 emulates receiving 255 BGP updates and withdraws. Checks route counts.
 func TestFSM255UpdatesIPv6(t *testing.T) {
-	fsmA := newFSM2(&peer{
+	fsmA := newFSM(&peer{
 		addr:     bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0xffff, 0, 0, 0, 1),
 		routerID: bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(),
 		ipv6: &familyParameters{
@@ -138,8 +138,8 @@ func TestFSM255UpdatesIPv6(t *testing.T) {
 			exportFilter: filter.NewAcceptAllFilter(),
 		},
 	})
-	fsmA.options.SupportsMultiProtocol = true
 
+	fsmA.options.MultiProtocolIPv6 = true
 	fsmA.holdTimer = time.NewTimer(time.Second * 90)
 	fsmA.keepaliveTimer = time.NewTimer(time.Second * 30)
 	fsmA.connectRetryTimer = time.NewTimer(time.Second * 120)
@@ -323,7 +323,7 @@ func TestOpenMessage(t *testing.T) {
 				},
 			}
 
-			fsm := newFSM2(&p)
+			fsm := newFSM(&p)
 			msg := fsm.openMessage()
 
 			assert.Equal(t, &test.expected, msg)
diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go
index bde263b504a590b411dc02291f64fe578d282263..b70534b0898a2c3b3a68d4509e47e4ae17039a97 100644
--- a/protocols/bgp/server/peer.go
+++ b/protocols/bgp/server/peer.go
@@ -177,7 +177,7 @@ func newPeer(c config.Peer, server *bgpServer) (*peer, error) {
 		Value: caps,
 	})
 
-	p.fsms = append(p.fsms, NewActiveFSM2(p))
+	p.fsms = append(p.fsms, NewActiveFSM(p))
 
 	return p, nil
 }
diff --git a/protocols/bgp/server/server.go b/protocols/bgp/server/server.go
index 170ca0a2e327ea0c49045c88d1070d4e5f6ca005..d6d50f5c3941556c46a6ad702c0713f6f2640d61 100644
--- a/protocols/bgp/server/server.go
+++ b/protocols/bgp/server/server.go
@@ -96,7 +96,7 @@ func (b *bgpServer) incomingConnectionWorker() {
 		}).Info("Incoming TCP connection")
 
 		log.WithField("Peer", peerAddr).Debug("Sending incoming TCP connection to fsm for peer")
-		fsm := NewActiveFSM2(peer)
+		fsm := NewActiveFSM(peer)
 		fsm.state = newActiveState(fsm)
 		fsm.startConnectRetryTimer()
 
diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go
index dd1c799985a6b6fb66b26381f26ebbfd4ab1c920..400c8470eff31ed29df849c2df7b0063bcfad54c 100644
--- a/protocols/bgp/server/update_sender.go
+++ b/protocols/bgp/server/update_sender.go
@@ -1,6 +1,7 @@
 package server
 
 import (
+	"fmt"
 	"sync"
 	"time"
 
@@ -129,7 +130,7 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
 }
 
 func (u *UpdateSender) updateOverhead() int {
-	if !u.fsm.options.SupportsMultiProtocol {
+	if u.afi == packet.IPv4AFI && !u.fsm.options.MultiProtocolIPv4 {
 		return 0
 	}
 
@@ -159,14 +160,18 @@ func (u *UpdateSender) sendUpdates(pathAttrs *packet.PathAttribute, updatePrefix
 }
 
 func (u *UpdateSender) updateMessageForPrefixes(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
-	if u.afi == packet.IPv4AFI && u.safi == packet.UnicastSAFI {
+	switch u.afi {
+	case packet.IPv4AFI:
+		if u.fsm.options.MultiProtocolIPv4 {
+			return u.bgpUpdateMultiProtocol(pfxs, pa, pathID)
+		}
 		return u.bgpUpdate(pfxs, pa, pathID)
+	case packet.IPv6AFI:
+		if u.fsm.options.MultiProtocolIPv6 {
+			return u.bgpUpdateMultiProtocol(pfxs, pa, pathID)
+		}
+		return nil
 	}
-
-	if u.fsm.options.SupportsMultiProtocol {
-		return u.bgpUpdateMultiProtocol(pfxs, pa, pathID)
-	}
-
 	return nil
 }
 
@@ -239,11 +244,31 @@ func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool {
 }
 
 func (u *UpdateSender) withdrawPrefix(pfx bnet.Prefix, p *route.Path) error {
-	if u.fsm.options.SupportsMultiProtocol {
-		return withDrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx, u.afi, u.safi)
+	if u.afi == packet.IPv4AFI {
+		return u.withdrawPrefixIPv4(pfx, p)
+	}
+
+	if u.afi == packet.IPv6AFI {
+		return u.withdrawPrefixIPv4(pfx, p)
+	}
+
+	return fmt.Errorf("Unsupported AFI: %v", u.afi)
+}
+
+func (u *UpdateSender) withdrawPrefixIPv4(pfx bnet.Prefix, p *route.Path) error {
+	if u.fsm.options.MultiProtocolIPv4 {
+		return withdrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx, u.afi, u.safi)
+	}
+
+	return withdrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p)
+}
+
+func (u *UpdateSender) withdrawPrefixIPv6(pfx bnet.Prefix, p *route.Path) error {
+	if !u.fsm.options.MultiProtocolIPv6 {
+		return fmt.Errorf("IPv6 was not negotiated")
 	}
 
-	return withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p)
+	return withdrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p)
 }
 
 // UpdateNewClient does nothing
diff --git a/protocols/bgp/server/update_sender_test.go b/protocols/bgp/server/update_sender_test.go
index 40719d6972a7b3f551d23823c4635666e5c59eac..6085dd8f4441f05ee7ebe7b803700a28ac9261fc 100644
--- a/protocols/bgp/server/update_sender_test.go
+++ b/protocols/bgp/server/update_sender_test.go
@@ -867,13 +867,13 @@ func TestSender(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		fsmA := newFSM2(&peer{
+		fsmA := newFSM(&peer{
 			addr: bnet.IPv4FromOctets(169, 254, 100, 100),
 		})
 
 		rib := locRIB.New()
 		if test.afi == packet.IPv6AFI {
-			fsmA.options.SupportsMultiProtocol = true
+			fsmA.options.MultiProtocolIPv6 = true
 			fsmA.ipv6Unicast = newFSMAddressFamily(packet.IPv6AFI, packet.UnicastSAFI, &familyParameters{
 				rib:          rib,
 				importFilter: filter.NewAcceptAllFilter(),
diff --git a/protocols/bgp/server/withdraw.go b/protocols/bgp/server/withdraw.go
index 2ab554b682691c57d0164d95eadef6afbcd14936..842d50f5497a31ff6562342f0f31eed79b5c32aa 100644
--- a/protocols/bgp/server/withdraw.go
+++ b/protocols/bgp/server/withdraw.go
@@ -10,9 +10,9 @@ import (
 	"github.com/bio-routing/bio-rd/route"
 )
 
-// withDrawPrefixes generates a BGPUpdate message and write it to the given
+// withdrawPrefixes generates a BGPUpdate message and write it to the given
 // io.Writer.
-func withDrawPrefixes(out io.Writer, opt *types.Options, prefixes ...net.Prefix) error {
+func withdrawPrefixes(out io.Writer, opt *types.Options, prefixes ...net.Prefix) error {
 	if len(prefixes) < 1 {
 		return nil
 	}
@@ -40,9 +40,9 @@ func withDrawPrefixes(out io.Writer, opt *types.Options, prefixes ...net.Prefix)
 
 }
 
-// withDrawPrefixesAddPath generates a BGPUpdateAddPath message and write it to the given
+// withdrawPrefixesAddPath generates a BGPUpdateAddPath message and write it to the given
 // io.Writer.
-func withDrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix, p *route.Path) error {
+func withdrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix, p *route.Path) error {
 	if p.Type != route.BGPPathType {
 		return errors.New("wrong path type, expected BGPPathType")
 	}
@@ -59,7 +59,7 @@ func withDrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix,
 	return serializeAndSendUpdate(out, update, opt)
 }
 
-func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix, afi uint16, safi uint8) error {
+func withdrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix, afi uint16, safi uint8) error {
 	update := &packet.BGPUpdate{
 		PathAttributes: &packet.PathAttribute{
 			TypeCode: packet.MultiProtocolUnreachNLRICode,
diff --git a/protocols/bgp/server/withdraw_test.go b/protocols/bgp/server/withdraw_test.go
index 17cb8751b8673dab38920a55db79699f6c643fb4..b379e2a00bf106fe8ff86c4866a351a2ddae8968 100644
--- a/protocols/bgp/server/withdraw_test.go
+++ b/protocols/bgp/server/withdraw_test.go
@@ -13,7 +13,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestWithDrawPrefixes(t *testing.T) {
+func TestWithdrawPrefixes(t *testing.T) {
 	testcases := []struct {
 		Name          string
 		Prefix        []net.Prefix
@@ -54,7 +54,7 @@ func TestWithDrawPrefixes(t *testing.T) {
 	for _, tc := range testcases {
 		buf := bytes.NewBuffer([]byte{})
 		opt := &types.Options{}
-		err := withDrawPrefixes(buf, opt, tc.Prefix...)
+		err := withdrawPrefixes(buf, opt, tc.Prefix...)
 		assert.Equal(t, tc.ExpectedError, err, "error mismatch in testcase %v", tc.Name)
 		assert.Equal(t, tc.Expected, buf.Bytes(), "expected different bytes in testcase %v", tc.Name)
 	}
@@ -90,7 +90,7 @@ func TestWithDrawPrefixesMultiProtocol(t *testing.T) {
 			opt := &types.Options{
 				AddPathRX: false,
 			}
-			err := withDrawPrefixesMultiProtocol(buf, opt, test.Prefix, packet.IPv6AFI, packet.UnicastSAFI)
+			err := withdrawPrefixesMultiProtocol(buf, opt, test.Prefix, packet.IPv6AFI, packet.UnicastSAFI)
 			if err != nil {
 				t.Fatalf("unexpected error: %v", err)
 			}
@@ -153,7 +153,7 @@ func TestWithDrawPrefixesAddPath(t *testing.T) {
 		opt := &types.Options{
 			AddPathRX: true,
 		}
-		err := withDrawPrefixesAddPath(buf, opt, tc.Prefix, tc.Path)
+		err := withdrawPrefixesAddPath(buf, opt, tc.Prefix, tc.Path)
 		assert.Equal(t, tc.ExpectedError, err, "error mismatch in testcase %v", tc.Name)
 		assert.Equal(t, tc.Expected, buf.Bytes(), "expected different bytes in testcase %v", tc.Name)
 	}
diff --git a/protocols/bgp/types/options.go b/protocols/bgp/types/options.go
index 8b96d6697b7262b53954a12663dff872fd3492b2..5bc87827dc6faff3948b0ec817d8151bdbc34d03 100644
--- a/protocols/bgp/types/options.go
+++ b/protocols/bgp/types/options.go
@@ -2,7 +2,8 @@ package types
 
 // Options represents options to the update sender, decoder and encoder
 type Options struct {
-	Supports4OctetASN     bool
-	SupportsMultiProtocol bool
-	AddPathRX             bool
+	Supports4OctetASN bool
+	AddPathRX         bool
+	MultiProtocolIPv4 bool
+	MultiProtocolIPv6 bool
 }