Skip to content

Commit 454d496

Browse files
committed
sdn: handle offset>0 fragments when validating service traffic
By default (set-frag normal) all fragments of a fragmented packet have a port number of 0. This is quite unhelpful; to get the right port number for all fragments requires un-fragmenting the packet with OVS's contrack capability, but this interacts badly with iptables' contrack capability. Instead, use the 'nx-frag' mode which keeps the port numbers in the first fragment of a fragmented packet, and add rules to allow subsequent fragments (with port=0) to pass through. Assume that the destination IP stack will reject offset>0 fragments that arrive without a corresponding offset=0 first fragment. We can't just drop the port checking because services can be manually created with a static service IP address, and perhaps users rely on creating two distinct services with the same service IP address, but differentiated via port numbers. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1419692
1 parent f45c2bd commit 454d496

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed

pkg/sdn/plugin/controller.go

+9
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ func (plugin *OsdnNode) SetupSDN() (bool, error) {
225225
if err != nil {
226226
return false, err
227227
}
228+
err = plugin.ovs.SetFrags("nx-match")
229+
if err != nil {
230+
return false, err
231+
}
228232
_ = plugin.ovs.DeletePort(VXLAN)
229233
_, err = plugin.ovs.AddPort(VXLAN, 1, "type=vxlan", `options:remote_ip="flow"`, `options:key="flow"`)
230234
if err != nil {
@@ -458,7 +462,10 @@ func (plugin *OsdnNode) AddServiceRules(service *kapi.Service, netID uint32) {
458462

459463
otx := plugin.ovs.NewTransaction()
460464
for _, port := range service.Spec.Ports {
465+
// Add one flow matching port #s for unfragmented packets and the first fragment
461466
otx.AddFlow(generateAddServiceRule(netID, service.Spec.ClusterIP, port.Protocol, int(port.Port)))
467+
// Add another flow matching port 0 to allow subsequent fragments through
468+
otx.AddFlow(generateAddServiceRule(netID, service.Spec.ClusterIP, port.Protocol, int(0)))
462469
if err := otx.EndTransaction(); err != nil {
463470
glog.Errorf("Error adding OVS flows for service %v, netid %d: %v", service, netID, err)
464471
}
@@ -471,6 +478,8 @@ func (plugin *OsdnNode) DeleteServiceRules(service *kapi.Service) {
471478
otx := plugin.ovs.NewTransaction()
472479
for _, port := range service.Spec.Ports {
473480
otx.DeleteFlows(generateDeleteServiceRule(service.Spec.ClusterIP, port.Protocol, int(port.Port)))
481+
// Also delete the fragment rule which uses port 0
482+
otx.DeleteFlows(generateDeleteServiceRule(service.Spec.ClusterIP, port.Protocol, int(0)))
474483
if err := otx.EndTransaction(); err != nil {
475484
glog.Errorf("Error deleting OVS flows for service %v: %v", service, err)
476485
}

pkg/util/ovs/ovs.go

+5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ func (ovsif *Interface) DeletePort(port string) error {
144144
return err
145145
}
146146

147+
func (ovsif *Interface) SetFrags(mode string) error {
148+
_, err := ovsif.exec(OVS_OFCTL, "set-frags", ovsif.bridge, mode)
149+
return err
150+
}
151+
147152
type Transaction struct {
148153
ovsif *Interface
149154
err error

0 commit comments

Comments
 (0)